Skip to content

Commit 3936c62

Browse files
committed
Updates for v1.2.0 and v1.0.1:
Velvet v1.2.0 * Added the new flag 'showvars' that dumps the variable each cycle/instruction * Added the 'allocInitList' function Velvc v1.0.1 * Reached 1.0.0, as Velvc is now in a usable state * Fixed the offset added to label positions so it aligns with the Info sections current size
1 parent 6fe2f4f commit 3936c62

21 files changed

Lines changed: 599 additions & 18 deletions

File tree

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,5 @@ bin/
1010
obj/
1111
.zig-cache
1212
.zig-out
13+
14+
*.cvelv

instructions.md

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@
66
1. ret
77
2. halt (int8)
88
3. call (fn)
9+
**Flags**<br>
10+
default: Treats the instruction arguments as an address and length for the name of a function
11+
1. Ignores the instruction arguments and instead pops off a function from the stack and runs it
912
4. push (literal)
1013

1114
**Flags**<br>
@@ -18,7 +21,7 @@
1821
6. dup
1922
7. swap
2023
8. rot
21-
9. set (int8)
24+
9. set (int16)
2225

2326
**Flags**<br>
2427
default: Instruction sets the variable of the given index to the stack item
@@ -27,10 +30,10 @@
2730

2831
**Flags**<br>
2932
default: Instruction acts like an unconditional jump
30-
1. Instruction acts only jumps if the stack item is `true`
31-
2. Instruction acts only jumps if the stack item is `false`
32-
3. Instruction acts only jumps if the error flag is true (a previous function call errored out)
33-
4. Instruction acts only jumps if the error flag is false (a previous function call did not error out)
33+
1. Instruction only jumps if the stack item is `true`
34+
2. Instruction only jumps if the stack item is `false`
35+
3. Instruction only jumps if the error flag is true (a previous function call errored out)
36+
4. Instruction only jumps if the error flag is false (a previous function call did not error out)
3437

3538
# Function Instructions
3639

@@ -51,7 +54,7 @@ These instructions don't actually exist, but are converted into function calls d
5154
* `div` -> `y, x = pop(), pop(); push(x / y)`
5255
* `pow` -> `y, x = pop(), pop(); push(pow(x, y))`
5356
* `log` -> `y, x = pop(), pop(); push(log(x, y))`
54-
* `log` -> `x = pop(); push(x!)`
57+
* `neg` -> `x = pop(); push(x!)`
5558
* `and` -> `y, x = pop(), pop(); push(x & y)`
5659
* `or` -> `y, x = pop(), pop(); push(x | y)`
5760
* `xor` -> `y, x = pop(), pop(); push(x ^ y)`

velvc/generation/emitter/emitter.go

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -209,10 +209,15 @@ func (va *VelvetAsm) CreateLabel(name string) {
209209
if _, ok := va.labels[name]; ok {
210210
panic(fmt.Sprintf("label '%s' already exists", name))
211211
}
212-
va.labels[name] = uint32(20 + len(va.instructions)*7)
212+
va.labels[name] = uint32(32 + len(va.instructions)*7)
213213
}
214214

215-
func (va *VelvetAsm) GetLabel(name string) uint32 {
215+
func (va VelvetAsm) HasLabel(name string) bool {
216+
_, ok := va.labels[name]
217+
return ok
218+
}
219+
220+
func (va VelvetAsm) GetLabel(name string) uint32 {
216221
if addr, ok := va.labels[name]; !ok {
217222
panic(fmt.Sprintf("label '%s' does not exist", name))
218223
} else {
@@ -258,6 +263,17 @@ func (va *VelvetAsm) Halt(code int8) {
258263
va.Emit(Halt, 0, uint16(code), 0)
259264
}
260265

266+
func (va *VelvetAsm) DoDirective(name string, args ...any) {
267+
switch name {
268+
case "vars":
269+
va.vars = uint16(args[0].(int))
270+
case "entry":
271+
va.SetEntry(uint32(args[0].(int)))
272+
default:
273+
panic("unknown directive '" + name + "'")
274+
}
275+
}
276+
261277
func (va *VelvetAsm) SetEntry(entryOffset uint32) {
262278
va.programEntry = entryOffset
263279
}

velvc/generation/generation.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package generation
2+
3+
import (
4+
"github.com/voidwyrm-2/velvet-vm/velvc/generation/emitter"
5+
"github.com/voidwyrm-2/velvet-vm/velvc/parser/nodes"
6+
)
7+
8+
type Generator struct {
9+
nodes []nodes.Node
10+
ve emitter.VelvetAsm
11+
}

velvc/lexer/tokens/tokens.go

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
package tokens
22

3-
import "fmt"
3+
import (
4+
"errors"
5+
"fmt"
6+
"strconv"
7+
)
48

59
type TokenType uint8
610

@@ -42,6 +46,13 @@ func New(kind TokenType, lit string, start, ln int) Token {
4246
return Token{kind: kind, lit: lit, start: start, ln: ln}
4347
}
4448

49+
func NewLit(kind TokenType, lit string) Token {
50+
t := Empty()
51+
t.kind = kind
52+
t.lit = lit
53+
return t
54+
}
55+
4556
func Empty() Token {
4657
return New(None, "", -1, -1)
4758
}
@@ -50,6 +61,10 @@ func (t Token) GetKind() TokenType {
5061
return t.kind
5162
}
5263

64+
func (t Token) GetLit() string {
65+
return t.lit
66+
}
67+
5368
func (t Token) GetLn() int {
5469
return t.ln
5570
}
@@ -62,6 +77,22 @@ func (t Token) IsLit(lit string) bool {
6277
return t.lit == lit
6378
}
6479

80+
func (t Token) Convert() (any, error) {
81+
switch t.kind {
82+
case Number, Address:
83+
return strconv.Atoi(t.lit)
84+
case String:
85+
return t.lit, nil
86+
case Bool:
87+
return t.lit == "true", nil
88+
}
89+
panic("invalid kind: " + t.Str())
90+
}
91+
6592
func (t Token) Str() string {
6693
return fmt.Sprintf("{%s, '%s', %d, %d}", t.kind.Str(), t.lit, t.start, t.ln)
6794
}
95+
96+
func (t Token) Err(format string, a ...any) error {
97+
return errors.New(fmt.Sprintf("error on line %d, col %d: ", t.ln, t.start) + fmt.Sprintf(format, a...))
98+
}

velvc/main.go

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@ import (
77
"os"
88
"strings"
99

10+
"github.com/voidwyrm-2/velvet-vm/velvc/generation/emitter"
1011
"github.com/voidwyrm-2/velvet-vm/velvc/lexer"
12+
"github.com/voidwyrm-2/velvet-vm/velvc/parser"
1113
"github.com/voidwyrm-2/velvet-vm/velvc/sectioner"
1214
)
1315

@@ -23,8 +25,11 @@ func readFile(fileName string) (string, error) {
2325
}
2426

2527
func main() {
26-
showTokens := flag.Bool("tokens", false, "Print the generated tokens")
28+
showTokens := flag.Bool("tokens", false, "Print the generated lexer tokens")
2729
showSectioned := flag.Bool("sectioned", false, "Print the sectioned tokens")
30+
showNodes := flag.Bool("nodes", false, "Print the generated parser nodes")
31+
32+
output := flag.String("o", "out", "The name of the output file")
2833

2934
flag.Parse()
3035

@@ -64,4 +69,30 @@ func main() {
6469
}
6570
fmt.Println(strings.Join(formatted, "\n"))
6671
}
72+
73+
parser := parser.New(sectionedTokens)
74+
75+
nodes, err := parser.Parse()
76+
if err != nil {
77+
fmt.Println(err.Error())
78+
os.Exit(1)
79+
} else if *showNodes {
80+
for _, n := range nodes {
81+
fmt.Println(n.Str())
82+
}
83+
}
84+
85+
ve := emitter.New(0)
86+
87+
for _, n := range nodes {
88+
if err := n.Generate(&ve); err != nil {
89+
fmt.Println(err.Error())
90+
os.Exit(1)
91+
}
92+
}
93+
94+
if err := ve.Write(*output + ".cvelv"); err != nil {
95+
fmt.Println(err.Error())
96+
os.Exit(1)
97+
}
6798
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package directive
2+
3+
import (
4+
"fmt"
5+
"strings"
6+
7+
"github.com/voidwyrm-2/velvet-vm/velvc/generation/emitter"
8+
"github.com/voidwyrm-2/velvet-vm/velvc/lexer/tokens"
9+
)
10+
11+
type DirectiveNode struct {
12+
name tokens.Token
13+
args []tokens.Token
14+
}
15+
16+
func New(name tokens.Token, args []tokens.Token) DirectiveNode {
17+
return DirectiveNode{name: name, args: args}
18+
}
19+
20+
func (dn DirectiveNode) Generate(ve *emitter.VelvetAsm) error {
21+
a := []any{}
22+
for _, arg := range dn.args {
23+
if v, err := arg.Convert(); err != nil {
24+
return err
25+
} else if ok := ve.HasLabel(arg.GetLit()); arg.IsKind(tokens.Ident) {
26+
if !ok {
27+
return arg.Err("label '%s' does not exist", arg.GetLit())
28+
}
29+
a = append(a, int(ve.GetLabel(arg.GetLit())))
30+
} else {
31+
a = append(a, v)
32+
}
33+
}
34+
ve.DoDirective(dn.name.GetLit(), a...)
35+
return nil
36+
}
37+
38+
func (dn DirectiveNode) Str() string {
39+
formatted := []string{}
40+
for _, t := range dn.args {
41+
formatted = append(formatted, t.Str())
42+
}
43+
return fmt.Sprintf("{ins: %s, args: %s}", dn.name.Str(), strings.Join(formatted, ", "))
44+
}

velvc/parser/nodes/halt/halt.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package halt
2+
3+
import (
4+
"fmt"
5+
"strconv"
6+
7+
"github.com/voidwyrm-2/velvet-vm/velvc/generation/emitter"
8+
"github.com/voidwyrm-2/velvet-vm/velvc/lexer/tokens"
9+
)
10+
11+
func assert[T any](v T, _ error) T {
12+
return v
13+
}
14+
15+
type HaltNode struct {
16+
instruction, exitCode tokens.Token
17+
}
18+
19+
func New(instruction, exitCode tokens.Token) HaltNode {
20+
return HaltNode{instruction: instruction, exitCode: exitCode}
21+
}
22+
23+
func (hn HaltNode) Generate(ve *emitter.VelvetAsm) error {
24+
ve.EmitNF32(emitter.Halt, uint32(assert(strconv.Atoi(hn.exitCode.GetLit()))))
25+
return nil
26+
}
27+
28+
func (hn HaltNode) Str() string {
29+
return fmt.Sprintf("{ins: %s, exitCode: %s}", hn.instruction.Str(), hn.exitCode.Str())
30+
}

velvc/parser/nodes/jump/jump.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package jump
2+
3+
import (
4+
"fmt"
5+
6+
"github.com/voidwyrm-2/velvet-vm/velvc/generation/emitter"
7+
"github.com/voidwyrm-2/velvet-vm/velvc/lexer/tokens"
8+
)
9+
10+
type JumpNode struct {
11+
instruction, label tokens.Token
12+
}
13+
14+
func New(instruction, label tokens.Token) JumpNode {
15+
return JumpNode{instruction: instruction, label: label}
16+
}
17+
18+
func (jn JumpNode) Generate(ve *emitter.VelvetAsm) error {
19+
ve.Emit32(emitter.Jump, map[string]uint8{"j": 0, "jt": 1, "jf": 2, "je": 3, "jne": 4}[jn.instruction.GetLit()], ve.GetLabel(jn.label.GetLit()))
20+
return nil
21+
}
22+
23+
func (jn JumpNode) Str() string {
24+
return fmt.Sprintf("{ins: %s, label: %s}", jn.instruction.Str(), jn.label.Str())
25+
}

velvc/parser/nodes/label/label.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package label
2+
3+
import (
4+
"fmt"
5+
6+
"github.com/voidwyrm-2/velvet-vm/velvc/generation/emitter"
7+
"github.com/voidwyrm-2/velvet-vm/velvc/lexer/tokens"
8+
)
9+
10+
type LabelNode struct {
11+
name tokens.Token
12+
}
13+
14+
func New(name tokens.Token) LabelNode {
15+
return LabelNode{name: name}
16+
}
17+
18+
func (ln LabelNode) Generate(ve *emitter.VelvetAsm) error {
19+
ve.CreateLabel(ln.name.GetLit())
20+
return nil
21+
}
22+
23+
func (ln LabelNode) Str() string {
24+
return fmt.Sprintf("{name: %s}", ln.name.Str())
25+
}

0 commit comments

Comments
 (0)