diff --git a/src/core/CompileAssign.go b/src/core/CompileAssign.go index ee9d022..56acd5c 100644 --- a/src/core/CompileAssign.go +++ b/src/core/CompileAssign.go @@ -8,6 +8,7 @@ import ( "git.urbach.dev/cli/q/src/errors" "git.urbach.dev/cli/q/src/eval" "git.urbach.dev/cli/q/src/token" + "git.urbach.dev/cli/q/src/types" ) // CompileAssign compiles an assign statement. @@ -56,11 +57,23 @@ func (f *Function) CompileAssign(node *ast.Assign) error { return err } + if !types.Is(rightValue.Type(), leftValue.Typ) { + return errors.New(&errors.TypeMismatch{Encountered: rightValue.Type().Name(), Expected: leftValue.Typ.Name()}, f.File, right.Token.Position) + } + leftSize := leftValue.Memory.Length rightSize := uint8(rightValue.Type().Size()) - if rightSize != 0 && leftSize != rightSize { - panic("memory store length mismatch") + switch { + case leftSize == 0: + leftSize = rightSize + leftValue.Memory.Length = rightSize + case rightSize == 0: + rightSize = leftSize + } + + if leftSize == 0 { + return errors.New(errors.UnknownMemorySize, f.File, operation.Position) } f.ValueToMemory(rightValue, leftValue.Memory) diff --git a/src/core/EvaluateArray.go b/src/core/EvaluateArray.go index a114bf4..2e34b71 100644 --- a/src/core/EvaluateArray.go +++ b/src/core/EvaluateArray.go @@ -21,28 +21,27 @@ func (f *Function) EvaluateArray(expr *expression.Expression) (*eval.Memory, err defer f.UseVariable(base) - memory := asm.Memory{ - Base: base.Value.Register, - Offset: 0, - OffsetRegister: -1, - Length: byte(1), + value := &eval.Memory{ + Memory: asm.Memory{ + Base: base.Value.Register, + Offset: 0, + OffsetRegister: -1, + Length: 0, + }, + } + + switch baseType := base.Value.Typ.(type) { + case *types.Array: + value.Typ = baseType.Of + value.Memory.Length = byte(baseType.Of.Size()) + case *types.Pointer: + value.Typ = baseType.To + value.Memory.Length = byte(baseType.To.Size()) + default: + return nil, errors.New(&errors.TypeMismatch{Encountered: base.Value.Typ.Name(), Expected: types.AnyPointer.Name()}, f.File, expr.Token.Position) } 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 } @@ -59,34 +58,12 @@ func (f *Function) EvaluateArray(expr *expression.Expression) (*eval.Memory, err switch index := index.(type) { case *eval.Number: - memory.Offset = int8(index.Number) + value.Memory.Offset = int8(index.Number) case *eval.Register: - memory.OffsetRegister = index.Register + value.Memory.OffsetRegister = index.Register default: panic(fmt.Errorf("%s: not implemented: %v", f.UniqueName, index)) } - array, isArray := base.Value.Typ.(*types.Array) - - if isArray { - value := &eval.Memory{ - Typ: array.Of, - Memory: memory, - } - - return value, nil - } - - pointer, isPointer := base.Value.Typ.(*types.Pointer) - - if isPointer { - value := &eval.Memory{ - Typ: pointer.To, - Memory: memory, - } - - return value, nil - } - - panic("invalid type") + return value, nil } diff --git a/src/errors/Common.go b/src/errors/Common.go index 93097ee..c628d64 100644 --- a/src/errors/Common.go +++ b/src/errors/Common.go @@ -21,5 +21,6 @@ var ( MissingParameter = &Base{"Missing parameter"} MissingType = &Base{"Missing type"} NotImplemented = &Base{"Not implemented"} + UnknownMemorySize = &Base{"Unknown memory size"} UntypedExpression = &Base{"Untyped expression"} ) diff --git a/src/scanner/scanStruct.go b/src/scanner/scanStruct.go index dc70838..8b26f23 100644 --- a/src/scanner/scanStruct.go +++ b/src/scanner/scanStruct.go @@ -26,8 +26,13 @@ func (s *Scanner) scanStruct(file *fs.File, tokens token.List, i int) (int, erro fieldPosition := i fieldName := tokens[i].Text(file.Bytes) i++ - fieldTypeName := tokens[i].Text(file.Bytes) - i++ + typePosition := i + + for i < len(tokens) && tokens[i].Kind != token.NewLine && tokens[i].Kind != token.BlockEnd { + i++ + } + + fieldTypeName := tokens[typePosition:i].Text(file.Bytes) structure.AddField(&types.Field{ Name: fieldName, diff --git a/tests/errors/TypeMismatch.q b/tests/errors/TypeMismatch.q index 09d6221..2088006 100644 --- a/tests/errors/TypeMismatch.q +++ b/tests/errors/TypeMismatch.q @@ -2,6 +2,6 @@ main() { writeToMemory(42) } -writeToMemory(p *any) { - p[0] = 'A' +writeToMemory(p *byte) { + [p] = 'A' } \ No newline at end of file diff --git a/tests/errors/TypeMismatch6.q b/tests/errors/TypeMismatch6.q new file mode 100644 index 0000000..71784aa --- /dev/null +++ b/tests/errors/TypeMismatch6.q @@ -0,0 +1,6 @@ +import mem + +main() { + a := mem.alloc(1) + a[0] = int64(1) +} \ No newline at end of file diff --git a/tests/errors_test.go b/tests/errors_test.go index 5fa7c11..ddbf815 100644 --- a/tests/errors_test.go +++ b/tests/errors_test.go @@ -49,11 +49,12 @@ var errs = []struct { {"MissingParameter3.q", errors.MissingParameter}, {"MissingType.q", errors.MissingType}, {"ReturnCountMismatch.q", &errors.ReturnCountMismatch{Count: 1, ExpectedCount: 0}}, - {"TypeMismatch.q", &errors.TypeMismatch{Expected: "*any", Encountered: "int", ParameterName: "p"}}, + {"TypeMismatch.q", &errors.TypeMismatch{Expected: "*uint8", Encountered: "int", ParameterName: "p"}}, {"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"}}, + {"TypeMismatch6.q", &errors.TypeMismatch{Expected: "uint8", Encountered: "int64"}}, {"UnknownIdentifier.q", &errors.UnknownIdentifier{Name: "x"}}, {"UnknownIdentifier2.q", &errors.UnknownIdentifier{Name: "x"}}, {"UnknownIdentifier3.q", &errors.UnknownIdentifier{Name: "x"}},