Reduced token size
This commit is contained in:
@ -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 {
|
||||
|
@ -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
|
||||
|
@ -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"
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
Reference in New Issue
Block a user