diff --git a/examples/hello/hello.q b/examples/hello/hello.q index e5101a2..2981aa1 100644 --- a/examples/hello/hello.q +++ b/examples/hello/hello.q @@ -1,4 +1,8 @@ main() { - syscall(1, 1, 4194305, 3) - syscall(60, 0) + let write = 1 + let exit = 60 + let stdout = 1 + + syscall(write, stdout, 4194305, 3) + syscall(exit, 0) } \ No newline at end of file diff --git a/src/build/Function.go b/src/build/Function.go index 729c5c5..8044009 100644 --- a/src/build/Function.go +++ b/src/build/Function.go @@ -16,6 +16,7 @@ type Function struct { Name string Head token.List Body token.List + Variables map[string]*Variable Assembler asm.Assembler } @@ -36,6 +37,16 @@ func (f *Function) Compile() { if line[0].Kind == token.Keyword { switch line[0].Text() { + case "let": + name := line[1].Text() + value := line[3:] + fmt.Println("[variable]", name, value) + + f.Variables[name] = &Variable{ + Value: line[3:], + IsConst: true, + } + case "return": f.Assembler.Return() } @@ -61,16 +72,33 @@ func (f *Function) Compile() { } for i, list := range parameters { - if list[0].Kind == token.Number { - numAsText := list[0].Text() - n, _ := strconv.Atoi(numAsText) + switch list[0].Kind { + case token.Identifier: + name := list[0].Text() + variable := f.Variables[name] + + if !variable.IsConst { + panic("Not implemented yet") + } + + n, _ := strconv.Atoi(variable.Value[0].Text()) f.Assembler.MoveRegisterNumber(x64.SyscallArgs[i], uint64(n)) + + case token.Number: + value := list[0].Text() + n, _ := strconv.Atoi(value) + f.Assembler.MoveRegisterNumber(x64.SyscallArgs[i], uint64(n)) + + default: + panic("Unknown expression") } } f.Assembler.Syscall() } } + + f.Assembler.Return() } // Lines returns the lines in the function body. diff --git a/src/build/Scan.go b/src/build/Scan.go index 6c56628..318c598 100644 --- a/src/build/Scan.go +++ b/src/build/Scan.go @@ -215,9 +215,10 @@ func scanFile(path string, functions chan<- *Function) error { } functions <- &Function{ - Name: tokens[nameStart].Text(), - Head: tokens[paramsStart:bodyStart], - Body: tokens[bodyStart : i+1], + Name: tokens[nameStart].Text(), + Head: tokens[paramsStart:bodyStart], + Body: tokens[bodyStart : i+1], + Variables: map[string]*Variable{}, } nameStart = -1 diff --git a/src/build/Variable.go b/src/build/Variable.go new file mode 100644 index 0000000..14cece9 --- /dev/null +++ b/src/build/Variable.go @@ -0,0 +1,9 @@ +package build + +import "git.akyoto.dev/cli/q/src/build/token" + +// Variable represents a variable in a function. +type Variable struct { + Value token.List + IsConst bool +} diff --git a/src/build/token/Keywords.go b/src/build/token/Keywords.go index adb8de7..a8eec3c 100644 --- a/src/build/token/Keywords.go +++ b/src/build/token/Keywords.go @@ -2,5 +2,6 @@ package token // Keywords defines the keywords used in the language. var Keywords = map[string]bool{ + "let": true, "return": true, } diff --git a/src/build/token/List.go b/src/build/token/List.go index 4c5953e..9cef514 100644 --- a/src/build/token/List.go +++ b/src/build/token/List.go @@ -13,7 +13,7 @@ func (list List) String() string { var last Token for _, t := range list { - if t.Kind == Identifier && last.Kind == Separator { + if last.Kind == Keyword || last.Kind == Separator { builder.WriteByte(' ') } diff --git a/src/build/token/Tokenize.go b/src/build/token/Tokenize.go index 213adb6..53cdbb6 100644 --- a/src/build/token/Tokenize.go +++ b/src/build/token/Tokenize.go @@ -70,6 +70,9 @@ func Tokenize(buffer []byte) List { case ']': tokens = append(tokens, Token{ArrayEnd, i, arrayEndBytes}) + case '=', ':', '+', '-', '*', '/', '<', '>', '!': + tokens = append(tokens, Token{Operator, i, buffer[i : i+1]}) + // Separator case ',': tokens = append(tokens, Token{Separator, i, separatorBytes}) @@ -147,3 +150,7 @@ func isNumber(c byte) bool { func isNumberStart(c byte) bool { return isNumber(c) || c == '-' } + +func isOperator(c byte) bool { + return c == '=' || c == ':' || c == '+' || c == '-' || c == '*' || c == '/' || c == '<' || c == '>' || c == '!' +}