Replaced builtin store function with a new syntax
This commit is contained in:
@ -7,6 +7,6 @@ alloc(length int) -> []byte {
|
|||||||
return x
|
return x
|
||||||
}
|
}
|
||||||
|
|
||||||
store(x, 8, length)
|
[x] = length
|
||||||
return x + 8
|
return x + 8
|
||||||
}
|
}
|
@ -5,7 +5,7 @@ alloc(length int) -> []byte {
|
|||||||
return x
|
return x
|
||||||
}
|
}
|
||||||
|
|
||||||
store(x, 8, length)
|
[x] = length
|
||||||
return x + 8
|
return x + 8
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,9 +4,9 @@ import sys
|
|||||||
create(func *any) -> int {
|
create(func *any) -> int {
|
||||||
stack := sys.mmap(0, 4096, 0x1|0x2, 0x02|0x20|0x100)
|
stack := sys.mmap(0, 4096, 0x1|0x2, 0x02|0x20|0x100)
|
||||||
stack += 4096 - 8
|
stack += 4096 - 8
|
||||||
store(stack, 8, core.exit)
|
[stack] = core.exit
|
||||||
stack -= 8
|
stack -= 8
|
||||||
store(stack, 8, func)
|
[stack] = func
|
||||||
return sys.clone(clone.vm|clone.fs|clone.files|clone.sighand|clone.parent|clone.thread|clone.io, stack, 0, 0, 0)
|
return sys.clone(clone.vm|clone.fs|clone.files|clone.sighand|clone.parent|clone.thread|clone.io, stack, 0, 0, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,6 +56,13 @@ func (f *Function) CompileAssign(node *ast.Assign) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
leftSize := leftValue.Memory.Length
|
||||||
|
rightSize := uint8(rightValue.Type().Size())
|
||||||
|
|
||||||
|
if rightSize != 0 && leftSize != rightSize {
|
||||||
|
panic("memory store length mismatch")
|
||||||
|
}
|
||||||
|
|
||||||
f.ValueToMemory(rightValue, leftValue.Memory)
|
f.ValueToMemory(rightValue, leftValue.Memory)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -41,9 +41,6 @@ func (f *Function) CompileCall(root *expression.Expression) ([]*Parameter, error
|
|||||||
|
|
||||||
case "delete":
|
case "delete":
|
||||||
return nil, f.CompileDelete(root)
|
return nil, f.CompileDelete(root)
|
||||||
|
|
||||||
case "store":
|
|
||||||
return nil, f.CompileMemoryStore(root)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,7 +46,7 @@ func (f *Function) CompileFor(loop *ast.For) error {
|
|||||||
panic("could not recognize loop header")
|
panic("could not recognize loop header")
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err := f.ExpressionToRegister(from, counter)
|
typ, err := f.ExpressionToRegister(from, counter)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -98,6 +98,7 @@ func (f *Function) CompileFor(loop *ast.For) error {
|
|||||||
variable = &scope.Variable{
|
variable = &scope.Variable{
|
||||||
Name: name,
|
Name: name,
|
||||||
Value: eval.Register{
|
Value: eval.Register{
|
||||||
|
Typ: typ,
|
||||||
Register: counter,
|
Register: counter,
|
||||||
Alive: ast.Count(loop.Body, f.File.Bytes, token.Identifier, name),
|
Alive: ast.Count(loop.Body, f.File.Bytes, token.Identifier, name),
|
||||||
},
|
},
|
||||||
|
@ -1,36 +0,0 @@
|
|||||||
package core
|
|
||||||
|
|
||||||
import (
|
|
||||||
"git.urbach.dev/cli/q/src/asm"
|
|
||||||
"git.urbach.dev/cli/q/src/errors"
|
|
||||||
"git.urbach.dev/cli/q/src/expression"
|
|
||||||
)
|
|
||||||
|
|
||||||
// CompileMemoryStore compiles a variable-width store to memory.
|
|
||||||
func (f *Function) CompileMemoryStore(root *expression.Expression) error {
|
|
||||||
parameters := root.Children[1:]
|
|
||||||
name := parameters[0].Token.Text(f.File.Bytes)
|
|
||||||
numBytes, err := f.ToNumber(parameters[1].Token)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
value := parameters[2]
|
|
||||||
variable := f.VariableByName(name)
|
|
||||||
|
|
||||||
if variable == nil {
|
|
||||||
return errors.New(&errors.UnknownIdentifier{Name: name}, f.File, parameters[0].Token.Position)
|
|
||||||
}
|
|
||||||
|
|
||||||
defer f.UseVariable(variable)
|
|
||||||
|
|
||||||
memory := asm.Memory{
|
|
||||||
Base: variable.Value.Register,
|
|
||||||
OffsetRegister: -1,
|
|
||||||
Length: byte(numBytes),
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = f.ExpressionToMemory(value, memory)
|
|
||||||
return err
|
|
||||||
}
|
|
@ -28,6 +28,24 @@ func (f *Function) EvaluateArray(expr *expression.Expression) (*eval.Memory, err
|
|||||||
Length: byte(1),
|
Length: byte(1),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if len(expr.Children) == 1 {
|
||||||
|
pointer, isPointer := base.Value.Typ.(*types.Pointer)
|
||||||
|
|
||||||
|
if !isPointer {
|
||||||
|
return nil, errors.New(&errors.TypeMismatch{Encountered: base.Value.Typ.Name(), Expected: types.AnyPointer.Name()}, f.File, expr.Token.Position)
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: This is a hack that needs to be removed
|
||||||
|
memory.Length = 8
|
||||||
|
|
||||||
|
value := &eval.Memory{
|
||||||
|
Typ: pointer.To,
|
||||||
|
Memory: memory,
|
||||||
|
}
|
||||||
|
|
||||||
|
return value, nil
|
||||||
|
}
|
||||||
|
|
||||||
indexExpr := expr.Children[1]
|
indexExpr := expr.Children[1]
|
||||||
index, err := f.Evaluate(indexExpr)
|
index, err := f.Evaluate(indexExpr)
|
||||||
|
|
||||||
|
@ -112,6 +112,11 @@ func TestParse(t *testing.T) {
|
|||||||
{"Array access 6", "a.b()[c]", "(@ (λ (. a b)) c)"},
|
{"Array access 6", "a.b()[c]", "(@ (λ (. a b)) c)"},
|
||||||
{"Array access 7", "a.b(c)[d]", "(@ (λ (. a b) c) d)"},
|
{"Array access 7", "a.b(c)[d]", "(@ (λ (. a b) c) d)"},
|
||||||
{"Array access 8", "a.b(c)[d][e]", "(@ (@ (λ (. a b) c) d) e)"},
|
{"Array access 8", "a.b(c)[d][e]", "(@ (@ (λ (. a b) c) d) e)"},
|
||||||
|
|
||||||
|
{"Dereferencing", "[a]", "(@ a)"},
|
||||||
|
{"Dereferencing 2", "[a+b]", "(@ (+ a b))"},
|
||||||
|
{"Dereferencing 3", "[a+b]=c", "(= (@ (+ a b)) c)"},
|
||||||
|
{"Dereferencing 3", "[a+b]=c+d", "(= (@ (+ a b)) (+ c d))"},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
|
@ -75,8 +75,17 @@ func Parse(tokens []token.Token) *Expression {
|
|||||||
group.Precedence = math.MaxInt8
|
group.Precedence = math.MaxInt8
|
||||||
|
|
||||||
if cursor == nil {
|
if cursor == nil {
|
||||||
cursor = group
|
if t.Kind == token.ArrayEnd {
|
||||||
root = group
|
cursor = New()
|
||||||
|
cursor.Token.Position = tokens[groupPosition].Position
|
||||||
|
cursor.Token.Kind = token.Array
|
||||||
|
cursor.Precedence = precedence(token.Array)
|
||||||
|
cursor.AddChild(group)
|
||||||
|
root = cursor
|
||||||
|
} else {
|
||||||
|
cursor = group
|
||||||
|
root = group
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
cursor.AddChild(group)
|
cursor.AddChild(group)
|
||||||
}
|
}
|
||||||
|
4
tests/errors/TypeMismatch5.q
Normal file
4
tests/errors/TypeMismatch5.q
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
main() {
|
||||||
|
a := 1
|
||||||
|
[a] = 2
|
||||||
|
}
|
@ -51,6 +51,9 @@ var errs = []struct {
|
|||||||
{"ReturnCountMismatch.q", &errors.ReturnCountMismatch{Count: 1, ExpectedCount: 0}},
|
{"ReturnCountMismatch.q", &errors.ReturnCountMismatch{Count: 1, ExpectedCount: 0}},
|
||||||
{"TypeMismatch.q", &errors.TypeMismatch{Expected: "*any", Encountered: "int", ParameterName: "p"}},
|
{"TypeMismatch.q", &errors.TypeMismatch{Expected: "*any", Encountered: "int", ParameterName: "p"}},
|
||||||
{"TypeMismatch2.q", &errors.TypeMismatch{Expected: "[]any", Encountered: "int", ParameterName: "array"}},
|
{"TypeMismatch2.q", &errors.TypeMismatch{Expected: "[]any", Encountered: "int", ParameterName: "array"}},
|
||||||
|
{"TypeMismatch3.q", &errors.TypeMismatch{Expected: "int", Encountered: "[]uint8"}},
|
||||||
|
{"TypeMismatch4.q", &errors.TypeMismatch{Expected: "int", Encountered: "[]uint8"}},
|
||||||
|
{"TypeMismatch5.q", &errors.TypeMismatch{Expected: "*any", Encountered: "int64"}},
|
||||||
{"UnknownIdentifier.q", &errors.UnknownIdentifier{Name: "x"}},
|
{"UnknownIdentifier.q", &errors.UnknownIdentifier{Name: "x"}},
|
||||||
{"UnknownIdentifier2.q", &errors.UnknownIdentifier{Name: "x"}},
|
{"UnknownIdentifier2.q", &errors.UnknownIdentifier{Name: "x"}},
|
||||||
{"UnknownIdentifier3.q", &errors.UnknownIdentifier{Name: "x"}},
|
{"UnknownIdentifier3.q", &errors.UnknownIdentifier{Name: "x"}},
|
||||||
|
Reference in New Issue
Block a user