Implemented expression parsing

This commit is contained in:
2024-06-16 16:57:33 +02:00
parent 864c9c7b43
commit ef16bdb4c7
18 changed files with 618 additions and 99 deletions

View File

@ -7,6 +7,7 @@ import (
"git.akyoto.dev/cli/q/src/build/arch/x64"
"git.akyoto.dev/cli/q/src/build/asm"
"git.akyoto.dev/cli/q/src/build/config"
"git.akyoto.dev/cli/q/src/build/expression"
"git.akyoto.dev/cli/q/src/build/fs"
"git.akyoto.dev/cli/q/src/build/token"
"git.akyoto.dev/cli/q/src/errors"
@ -28,6 +29,7 @@ type Function struct {
func (f *Function) Compile() {
if config.Verbose {
ansi.Bold.Println(f.Name)
ansi.Dim.Println("╭────────────────────────────────────────────────────────────")
}
start := 0
@ -76,6 +78,7 @@ func (f *Function) Compile() {
f.Assembler.Return()
if config.Verbose {
ansi.Dim.Println("╰────────────────────────────────────────────────────────────")
f.PrintAsm()
}
}
@ -84,6 +87,7 @@ func (f *Function) Compile() {
func (f *Function) PrintAsm() {
fmt.Println()
ansi.Bold.Println(f.Name + ".asm")
ansi.Dim.Println("╭────────────────────────────────────────────────────────────")
for _, x := range f.Assembler.Instructions {
ansi.Dim.Print("│ ")
@ -95,6 +99,8 @@ func (f *Function) PrintAsm() {
fmt.Print("\n")
}
ansi.Dim.Println("╰────────────────────────────────────────────────────────────")
}
// CompileInstruction compiles a single instruction.
@ -104,91 +110,93 @@ func (f *Function) CompileInstruction(line token.List) error {
fmt.Println(line)
}
if len(line) == 0 {
return nil
}
if line[0].Kind == token.Keyword {
switch line[0].Text() {
case "return":
f.Assembler.Return()
default:
return errors.New(&errors.KeywordNotImplemented{Keyword: line[0].Text()}, f.File, line[0].Position)
}
}
expr := expression.Parse(line)
if expr == nil {
return nil
}
defer expr.Close()
if config.Verbose {
ansi.Dim.Print("├───○ exp ")
fmt.Println(expr)
}
if expr.Token.Kind == token.Number || expr.Token.Kind == token.Identifier {
return errors.New(&errors.InvalidInstruction{Instruction: expr.Token.Text()}, f.File, expr.Token.Position)
}
if expr.Token.Text() == ":=" {
if len(expr.Children) < 2 {
return errors.New(errors.MissingAssignValue, f.File, expr.LastChild().Token.After())
}
name := expr.Children[0]
value := expr.Children[1]
if config.Verbose {
ansi.Dim.Print("├───○ var ")
fmt.Println(name, value)
}
expr.RemoveChild(value)
f.Variables[name.Token.Text()] = &Variable{
Name: name.Token.Text(),
Value: value,
IsConst: true,
}
return nil
}
if len(line) < 2 {
return errors.New(&errors.InvalidInstruction{Instruction: line[0].Text()}, f.File, line[0].Position)
}
if expr.Token.Text() == "call" && expr.Children[0].Token.Text() == "syscall" {
parameters := expr.Children[1:]
if line[0].Kind == token.Identifier {
if line[1].Kind == token.Define {
name := line[0].Text()
value := line[2:]
for i, parameter := range parameters {
switch parameter.Token.Kind {
case token.Identifier:
name := parameter.Token.Text()
variable, exists := f.Variables[name]
if len(value) == 0 {
return errors.New(errors.MissingAssignValue, f.File, line[1].After())
}
if config.Verbose {
ansi.Dim.Printf("├── var ")
fmt.Println(name, "=", value)
}
f.Variables[name] = &Variable{
Name: name,
Value: value,
IsConst: true,
}
return nil
}
switch line[0].Text() {
case "syscall":
paramTokens := line[2 : len(line)-1]
start := 0
i := 0
var parameters []token.List
for i < len(paramTokens) {
if paramTokens[i].Kind == token.Separator {
parameters = append(parameters, paramTokens[start:i])
start = i + 1
if !exists {
panic("Unknown identifier " + name)
}
i++
}
if i != start {
parameters = append(parameters, paramTokens[start:i])
}
for i, list := range parameters {
switch list[0].Kind {
case token.Identifier:
name := list[0].Text()
variable, exists := f.Variables[name]
if !exists {
panic("Unknown identifier " + 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")
if !variable.IsConst {
panic("Not implemented yet")
}
}
f.Assembler.Syscall()
n, _ := strconv.Atoi(variable.Value.Token.Text())
f.Assembler.MoveRegisterNumber(x64.SyscallArgs[i], uint64(n))
case token.Number:
value := parameter.Token.Text()
n, _ := strconv.Atoi(value)
f.Assembler.MoveRegisterNumber(x64.SyscallArgs[i], uint64(n))
default:
panic("Unknown expression")
}
}
f.Assembler.Syscall()
return nil
}
return nil