Reduced token size

This commit is contained in:
2024-07-21 14:35:06 +02:00
parent ca36d34cb9
commit 04ba68a075
47 changed files with 543 additions and 764 deletions

View File

@ -13,7 +13,7 @@ func (f *Function) Compare(comparison *expression.Expression) error {
right := comparison.Children[1]
if left.IsLeaf() && left.Token.Kind == token.Identifier {
name := left.Token.Text()
name := left.Token.Text(f.File.Bytes)
variable := f.VariableByName(name)
if variable == nil {

View File

@ -16,7 +16,7 @@ func (f *Function) CompileAssign(node *ast.Assign) error {
right := node.Expression.Children[1]
if left.IsLeaf() {
name := left.Token.Text()
name := left.Token.Text(f.File.Bytes)
variable := f.VariableByName(name)
if variable == nil {
@ -27,8 +27,8 @@ func (f *Function) CompileAssign(node *ast.Assign) error {
return f.Execute(operator, variable.Register, right)
}
if left.Token.Kind == token.Operator && left.Token.Text() == "@" {
name := left.Children[0].Token.Text()
if left.Token.Kind == token.Array {
name := left.Children[0].Token.Text(f.File.Bytes)
variable := f.VariableByName(name)
if variable == nil {
@ -38,13 +38,13 @@ func (f *Function) CompileAssign(node *ast.Assign) error {
defer f.useVariable(variable)
index := left.Children[1]
offset, err := strconv.Atoi(index.Token.Text())
offset, err := strconv.Atoi(index.Token.Text(f.File.Bytes))
if err != nil {
return err
}
num, err := strconv.Atoi(right.Token.Text())
num, err := strconv.Atoi(right.Token.Text(f.File.Bytes))
if err != nil {
return err

View File

@ -15,9 +15,9 @@ func (f *Function) CompileCall(root *expression.Expression) error {
funcName := ""
if funcNameRoot.IsLeaf() {
funcName = funcNameRoot.Token.Text()
funcName = funcNameRoot.Token.Text(f.File.Bytes)
} else {
funcName = funcNameRoot.Children[0].Token.Text() + funcNameRoot.Token.Text() + funcNameRoot.Children[1].Token.Text()
funcName = funcNameRoot.Children[0].Token.Text(f.File.Bytes) + funcNameRoot.Token.Text(f.File.Bytes) + funcNameRoot.Children[1].Token.Text(f.File.Bytes)
}
isSyscall := funcName == "syscall"

View File

@ -4,12 +4,13 @@ import (
"fmt"
"git.akyoto.dev/cli/q/src/build/expression"
"git.akyoto.dev/cli/q/src/build/token"
)
// CompileCondition inserts code to jump to the start label or end label depending on the truth of the condition.
func (f *Function) CompileCondition(condition *expression.Expression, successLabel string, failLabel string) error {
switch condition.Token.Text() {
case "||":
switch condition.Token.Kind {
case token.LogicalOr:
f.count.subBranch++
leftFailLabel := fmt.Sprintf("%s_false_%d", f.Name, f.count.subBranch)
@ -21,22 +22,22 @@ func (f *Function) CompileCondition(condition *expression.Expression, successLab
return err
}
f.JumpIfTrue(left.Token.Text(), successLabel)
f.JumpIfTrue(left.Token.Kind, successLabel)
// Right
f.AddLabel(leftFailLabel)
right := condition.Children[1]
err = f.CompileCondition(right, successLabel, failLabel)
if condition.Parent != nil && condition.Parent.Token.Text() == "||" && condition != condition.Parent.LastChild() {
f.JumpIfTrue(right.Token.Text(), successLabel)
if condition.Parent != nil && condition.Parent.Token.Kind == token.LogicalOr && condition != condition.Parent.LastChild() {
f.JumpIfTrue(right.Token.Kind, successLabel)
} else {
f.JumpIfFalse(right.Token.Text(), failLabel)
f.JumpIfFalse(right.Token.Kind, failLabel)
}
return err
case "&&":
case token.LogicalAnd:
f.count.subBranch++
leftSuccessLabel := fmt.Sprintf("%s_true_%d", f.Name, f.count.subBranch)
@ -48,17 +49,17 @@ func (f *Function) CompileCondition(condition *expression.Expression, successLab
return err
}
f.JumpIfFalse(left.Token.Text(), failLabel)
f.JumpIfFalse(left.Token.Kind, failLabel)
// Right
f.AddLabel(leftSuccessLabel)
right := condition.Children[1]
err = f.CompileCondition(right, successLabel, failLabel)
if condition.Parent != nil && condition.Parent.Token.Text() == "||" && condition != condition.Parent.LastChild() {
f.JumpIfTrue(right.Token.Text(), successLabel)
if condition.Parent != nil && condition.Parent.Token.Kind == token.LogicalOr && condition != condition.Parent.LastChild() {
f.JumpIfTrue(right.Token.Kind, successLabel)
} else {
f.JumpIfFalse(right.Token.Text(), failLabel)
f.JumpIfFalse(right.Token.Kind, failLabel)
}
return err
@ -67,7 +68,7 @@ func (f *Function) CompileCondition(condition *expression.Expression, successLab
err := f.Compare(condition)
if condition.Parent == nil {
f.JumpIfFalse(condition.Token.Text(), failLabel)
f.JumpIfFalse(condition.Token.Kind, failLabel)
}
return err

View File

@ -8,13 +8,13 @@ import (
// CompileDefinition compiles a variable definition.
func (f *Function) CompileDefinition(node *ast.Define) error {
name := node.Name.Text()
name := node.Name.Text(f.File.Bytes)
if f.identifierExists(name) {
return errors.New(&errors.VariableAlreadyExists{Name: name}, f.File, node.Name.Position)
}
uses := token.Count(f.Body, token.Identifier, name) - 1
uses := token.Count(f.Body, f.File.Bytes, token.Identifier, name) - 1
if uses == 0 {
return errors.New(&errors.UnusedVariable{Name: name}, f.File, node.Name.Position)

View File

@ -18,7 +18,7 @@ func (f *Function) CompileIf(branch *ast.If) error {
}
f.AddLabel(success)
f.PushScope(branch.Body)
f.PushScope(branch.Body, f.File.Bytes)
err = f.CompileAST(branch.Body)
f.PopScope()
f.AddLabel(fail)

View File

@ -12,7 +12,7 @@ func (f *Function) CompileLoop(loop *ast.Loop) error {
f.count.loop++
label := fmt.Sprintf("%s_loop_%d", f.Name, f.count.loop)
f.AddLabel(label)
scope := f.PushScope(loop.Body)
scope := f.PushScope(loop.Body, f.File.Bytes)
scope.InLoop = true
err := f.CompileAST(loop.Body)
f.Jump(asm.JUMP, label)

View File

@ -7,8 +7,8 @@ import (
)
// CompileTokens compiles a token list.
func (f *Function) CompileTokens(tokens token.List) error {
body, err := ast.Parse(tokens)
func (f *Function) CompileTokens(tokens []token.Token) error {
body, err := ast.Parse(tokens, f.File.Bytes)
if err != nil {
err.(*errors.Error).File = f.File

View File

@ -12,7 +12,7 @@ import (
func (f *Function) ExecuteLeaf(operation token.Token, register cpu.Register, operand token.Token) error {
switch operand.Kind {
case token.Identifier:
name := operand.Text()
name := operand.Text(f.File.Bytes)
variable := f.VariableByName(name)
if variable == nil {
@ -23,7 +23,7 @@ func (f *Function) ExecuteLeaf(operation token.Token, register cpu.Register, ope
return f.ExecuteRegisterRegister(operation, register, variable.Register)
case token.Number:
value := operand.Text()
value := operand.Text(f.File.Bytes)
number, err := strconv.Atoi(value)
if err != nil {
@ -33,7 +33,7 @@ func (f *Function) ExecuteLeaf(operation token.Token, register cpu.Register, ope
return f.ExecuteRegisterNumber(operation, register, number)
case token.String:
if operation.Text() == "=" {
if operation.Kind == token.Assign {
return f.TokenToRegister(operand, register)
}
}

View File

@ -9,27 +9,27 @@ import (
// ExecuteRegisterNumber performs an operation on a register and a number.
func (f *Function) ExecuteRegisterNumber(operation token.Token, register cpu.Register, number int) error {
switch operation.Text() {
case "+", "+=":
switch operation.Kind {
case token.Add, token.AddAssign:
f.RegisterNumber(asm.ADD, register, number)
case "-", "-=":
case token.Sub, token.SubAssign:
f.RegisterNumber(asm.SUB, register, number)
case "*", "*=":
case token.Mul, token.MulAssign:
f.RegisterNumber(asm.MUL, register, number)
case "/", "/=":
case token.Div, token.DivAssign:
f.RegisterNumber(asm.DIV, register, number)
case "==", "!=", "<", "<=", ">", ">=":
case token.Equal, token.NotEqual, token.Less, token.LessEqual, token.Greater, token.GreaterEqual:
f.RegisterNumber(asm.COMPARE, register, number)
case "=":
case token.Assign:
f.RegisterNumber(asm.MOVE, register, number)
default:
return errors.New(&errors.InvalidOperator{Operator: operation.Text()}, f.File, operation.Position)
return errors.New(&errors.InvalidOperator{Operator: operation.Text(f.File.Bytes)}, f.File, operation.Position)
}
return nil

View File

@ -9,27 +9,27 @@ import (
// ExecuteRegisterRegister performs an operation on two registers.
func (f *Function) ExecuteRegisterRegister(operation token.Token, destination cpu.Register, source cpu.Register) error {
switch operation.Text() {
case "+", "+=":
switch operation.Kind {
case token.Add, token.AddAssign:
f.RegisterRegister(asm.ADD, destination, source)
case "-", "-=":
case token.Sub, token.SubAssign:
f.RegisterRegister(asm.SUB, destination, source)
case "*", "*=":
case token.Mul, token.MulAssign:
f.RegisterRegister(asm.MUL, destination, source)
case "/", "/=":
case token.Div, token.DivAssign:
f.RegisterRegister(asm.DIV, destination, source)
case "==", "!=", "<", "<=", ">", ">=":
case token.Equal, token.NotEqual, token.Less, token.LessEqual, token.Greater, token.GreaterEqual:
f.RegisterRegister(asm.COMPARE, destination, source)
case "=":
case token.Assign:
f.RegisterRegister(asm.MOVE, destination, source)
default:
return errors.New(&errors.InvalidOperator{Operator: operation.Text()}, f.File, operation.Position)
return errors.New(&errors.InvalidOperator{Operator: operation.Text(f.File.Bytes)}, f.File, operation.Position)
}
return nil

View File

@ -13,7 +13,7 @@ type Function struct {
scope.Stack
Name string
File *fs.File
Body token.List
Body []token.Token
Assembler asm.Assembler
Functions map[string]*Function
Err error

View File

@ -2,22 +2,23 @@ package core
import (
"git.akyoto.dev/cli/q/src/build/asm"
"git.akyoto.dev/cli/q/src/build/token"
)
// JumpIfFalse jumps to the label if the previous comparison was false.
func (f *Function) JumpIfFalse(operator string, label string) {
func (f *Function) JumpIfFalse(operator token.Kind, label string) {
switch operator {
case "==":
case token.Equal:
f.Jump(asm.JNE, label)
case "!=":
case token.NotEqual:
f.Jump(asm.JE, label)
case ">":
case token.Greater:
f.Jump(asm.JLE, label)
case "<":
case token.Less:
f.Jump(asm.JGE, label)
case ">=":
case token.GreaterEqual:
f.Jump(asm.JL, label)
case "<=":
case token.LessEqual:
f.Jump(asm.JG, label)
}
}

View File

@ -2,22 +2,23 @@ package core
import (
"git.akyoto.dev/cli/q/src/build/asm"
"git.akyoto.dev/cli/q/src/build/token"
)
// JumpIfTrue jumps to the label if the previous comparison was true.
func (f *Function) JumpIfTrue(operator string, label string) {
func (f *Function) JumpIfTrue(operator token.Kind, label string) {
switch operator {
case "==":
case token.Equal:
f.Jump(asm.JE, label)
case "!=":
case token.NotEqual:
f.Jump(asm.JNE, label)
case ">":
case token.Greater:
f.Jump(asm.JG, label)
case "<":
case token.Less:
f.Jump(asm.JL, label)
case ">=":
case token.GreaterEqual:
f.Jump(asm.JGE, label)
case "<=":
case token.LessEqual:
f.Jump(asm.JLE, label)
}
}

View File

@ -10,7 +10,7 @@ import (
)
// NewFunction creates a new function.
func NewFunction(name string, file *fs.File, body token.List) *Function {
func NewFunction(name string, file *fs.File, body []token.Token) *Function {
return &Function{
Name: name,
File: file,

View File

@ -15,7 +15,7 @@ import (
func (f *Function) TokenToRegister(t token.Token, register cpu.Register) error {
switch t.Kind {
case token.Identifier:
name := t.Text()
name := t.Text(f.File.Bytes)
variable := f.VariableByName(name)
if variable == nil {
@ -27,7 +27,7 @@ func (f *Function) TokenToRegister(t token.Token, register cpu.Register) error {
return nil
case token.Number:
value := t.Text()
value := t.Text(f.File.Bytes)
n, err := strconv.Atoi(value)
if err != nil {
@ -40,7 +40,7 @@ func (f *Function) TokenToRegister(t token.Token, register cpu.Register) error {
case token.String:
f.count.data++
label := fmt.Sprintf("%s_data_%d", f.Name, f.count.data)
value := t.Bytes[1 : len(t.Bytes)-1]
value := t.Bytes(f.File.Bytes)[1 : t.Length-1]
f.Assembler.SetData(label, value)
f.RegisterLabel(asm.MOVE, register, label)
return nil