From c0ffddaba81fff58615a36c7961c9f5f2ef1415f Mon Sep 17 00:00:00 2001 From: Eduard Urbach Date: Sun, 9 Feb 2025 20:25:37 +0100 Subject: [PATCH] Added array type --- lib/io/io.q | 10 +++++----- lib/mem/alloc_linux.q | 2 +- lib/mem/alloc_mac.q | 2 +- lib/mem/alloc_windows.q | 2 +- src/core/CompileReturn.go | 4 ++++ src/core/ExpressionToMemory.go | 4 ++-- src/core/ExpressionToRegister.go | 2 +- src/core/TokenToRegister.go | 4 ++-- src/types/Array.go | 18 ++++++++++++++++++ src/types/ByName.go | 13 ++++++++++++- src/types/Is.go | 12 ++++++++++++ src/types/Pointer.go | 4 ++-- src/types/types_test.go | 16 ++++++++++------ 13 files changed, 71 insertions(+), 22 deletions(-) create mode 100644 src/types/Array.go diff --git a/lib/io/io.q b/lib/io/io.q index 4349f94..545c810 100644 --- a/lib/io/io.q +++ b/lib/io/io.q @@ -1,21 +1,21 @@ import sys -in(buffer Pointer) -> Int { +in(buffer []Int8) -> Int { return sys.read(0, buffer, len(buffer)) } -out(message Pointer) -> Int { +out(message []Int8) -> Int { return sys.write(1, message, len(message)) } -error(message Pointer) -> Int { +error(message []Int8) -> Int { return sys.write(2, message, len(message)) } -read(fd Int, buffer Pointer) -> Int { +read(fd Int, buffer []Int8) -> Int { return sys.read(fd, buffer, len(buffer)) } -write(fd Int, message Pointer) -> Int { +write(fd Int, message []Int8) -> Int { return sys.write(fd, message, len(message)) } \ No newline at end of file diff --git a/lib/mem/alloc_linux.q b/lib/mem/alloc_linux.q index 2389b04..9b9878b 100644 --- a/lib/mem/alloc_linux.q +++ b/lib/mem/alloc_linux.q @@ -1,6 +1,6 @@ import sys -alloc(length Int) -> Pointer { +alloc(length Int) -> []Int8 { x := sys.mmap(0, length+8, 0x1|0x2, 0x02|0x20) if x < 0x1000 { diff --git a/lib/mem/alloc_mac.q b/lib/mem/alloc_mac.q index 6ffda84..128d40c 100644 --- a/lib/mem/alloc_mac.q +++ b/lib/mem/alloc_mac.q @@ -1,6 +1,6 @@ import sys -alloc(length Int) -> Pointer { +alloc(length Int) -> []Int8 { x := sys.mmap(0, length+8, 0x1|0x2, 0x02|0x1000) if x < 0x1000 { diff --git a/lib/mem/alloc_windows.q b/lib/mem/alloc_windows.q index d448dd0..50bb75d 100644 --- a/lib/mem/alloc_windows.q +++ b/lib/mem/alloc_windows.q @@ -1,6 +1,6 @@ import sys -alloc(length Int) -> Pointer { +alloc(length Int) -> []Int8 { x := sys.mmap(0, length+8, 0x0004, 0x3000) if x < 0x1000 { diff --git a/src/core/CompileReturn.go b/src/core/CompileReturn.go index 16180a8..f535936 100644 --- a/src/core/CompileReturn.go +++ b/src/core/CompileReturn.go @@ -26,6 +26,10 @@ func (f *Function) CompileReturn(node *ast.Return) error { } if !types.Is(typ, f.Output[i].Type) { + if f.Package == "mem" && f.Name == "alloc" { + return nil + } + return errors.New(&errors.TypeMismatch{ Encountered: typ.Name(), Expected: f.Output[i].Type.Name(), diff --git a/src/core/ExpressionToMemory.go b/src/core/ExpressionToMemory.go index 0176701..e73fe91 100644 --- a/src/core/ExpressionToMemory.go +++ b/src/core/ExpressionToMemory.go @@ -18,12 +18,12 @@ func (f *Function) ExpressionToMemory(node *expression.Expression, memory asm.Me if variable != nil { f.MemoryRegister(asm.STORE, memory, variable.Register) f.UseVariable(variable) - return types.PointerAny, nil + return types.AnyPointer, nil } if function != nil { f.MemoryLabel(asm.STORE, memory, function.UniqueName) - return types.PointerAny, nil + return types.AnyPointer, nil } return nil, errors.New(&errors.UnknownIdentifier{Name: name}, f.File, node.Token.Position) diff --git a/src/core/ExpressionToRegister.go b/src/core/ExpressionToRegister.go index a72b381..4157a1d 100644 --- a/src/core/ExpressionToRegister.go +++ b/src/core/ExpressionToRegister.go @@ -83,7 +83,7 @@ func (f *Function) ExpressionToRegister(node *expression.Expression, register cp return nil, err } - if typ == types.PointerAny && right.Token.Kind == token.Identifier && f.VariableByName(right.Token.Text(f.File.Bytes)).Type == types.PointerAny { + if typ == types.AnyPointer && right.Token.Kind == token.Identifier && f.VariableByName(right.Token.Text(f.File.Bytes)).Type == types.AnyPointer { typ = types.Int } diff --git a/src/core/TokenToRegister.go b/src/core/TokenToRegister.go index c467895..ed934cb 100644 --- a/src/core/TokenToRegister.go +++ b/src/core/TokenToRegister.go @@ -28,7 +28,7 @@ func (f *Function) TokenToRegister(t token.Token, register cpu.Register) (types. if function != nil { f.SaveRegister(register) f.RegisterLabel(asm.MOVE, register, function.UniqueName) - return types.PointerAny, nil + return types.AnyPointer, nil } return nil, errors.New(&errors.UnknownIdentifier{Name: name}, f.File, t.Position) @@ -55,7 +55,7 @@ func (f *Function) TokenToRegister(t token.Token, register cpu.Register) (types. label := f.AddBytes(slice) f.SaveRegister(register) f.RegisterLabel(asm.MOVE, register, label) - return types.PointerAny, nil + return types.String, nil default: return nil, errors.New(errors.InvalidExpression, f.File, t.Position) diff --git a/src/types/Array.go b/src/types/Array.go new file mode 100644 index 0000000..fd6add2 --- /dev/null +++ b/src/types/Array.go @@ -0,0 +1,18 @@ +package types + +var String = &Array{Of: Int8} + +// Array is the address of an object. +type Array struct { + Of Type +} + +// Name returns the type name. +func (a *Array) Name() string { + return "[]" + a.Of.Name() +} + +// Size returns the total size in bytes. +func (a *Array) Size() int { + return 8 +} diff --git a/src/types/ByName.go b/src/types/ByName.go index 765fb8f..9c43a19 100644 --- a/src/types/ByName.go +++ b/src/types/ByName.go @@ -17,6 +17,17 @@ func ByName(name string, pkg string, structs map[string]*Struct) Type { return nil } + if strings.HasPrefix(name, "[]") { + to := strings.TrimPrefix(name, "[]") + typ := ByName(to, pkg, structs) + + if typ != nil { + return &Array{Of: typ} + } + + return nil + } + switch name { case "Int": return Int @@ -35,7 +46,7 @@ func ByName(name string, pkg string, structs map[string]*Struct) Type { case "Float32": return Float32 case "Pointer": - return PointerAny + return AnyPointer } typ, exists := structs[pkg+"."+name] diff --git a/src/types/Is.go b/src/types/Is.go index 9adbac5..059086f 100644 --- a/src/types/Is.go +++ b/src/types/Is.go @@ -17,5 +17,17 @@ func Is(a Type, b Type) bool { return true } + aArray, aIsArray := a.(*Array) + + if aIsArray && bIsPointer && (bPointer.To == nil || aArray.Of == bPointer.To) { + return true + } + + bArray, bIsArray := b.(*Array) + + if aIsArray && bIsArray && aArray.Of == bArray.Of { + return true + } + return false } diff --git a/src/types/Pointer.go b/src/types/Pointer.go index 06a712e..cc08bd3 100644 --- a/src/types/Pointer.go +++ b/src/types/Pointer.go @@ -1,6 +1,6 @@ package types -var PointerAny = &Pointer{To: nil} +var AnyPointer = &Pointer{To: nil} // Pointer is the address of an object. type Pointer struct { @@ -13,7 +13,7 @@ func (p *Pointer) Name() string { return "Pointer" } - return "Pointer:" + p.To.Name() + return "*" + p.To.Name() } // Size returns the total size in bytes. diff --git a/src/types/types_test.go b/src/types/types_test.go index e134ad1..f8f3818 100644 --- a/src/types/types_test.go +++ b/src/types/types_test.go @@ -9,8 +9,10 @@ import ( func TestName(t *testing.T) { assert.Equal(t, types.Int.Name(), "Int64") - assert.Equal(t, types.PointerAny.Name(), "Pointer") - assert.Equal(t, (&types.Pointer{To: types.Int}).Name(), "Pointer:Int64") + assert.Equal(t, types.AnyPointer.Name(), "Pointer") + assert.Equal(t, (&types.Pointer{To: types.Int}).Name(), "*Int64") + assert.Equal(t, (&types.Array{Of: types.Int}).Name(), "[]Int64") + assert.Equal(t, types.String.Name(), "[]Int8") } func TestSize(t *testing.T) { @@ -19,7 +21,8 @@ func TestSize(t *testing.T) { assert.Equal(t, types.Int16.Size(), 2) assert.Equal(t, types.Int32.Size(), 4) assert.Equal(t, types.Int64.Size(), 8) - assert.Equal(t, types.PointerAny.Size(), 8) + assert.Equal(t, types.AnyPointer.Size(), 8) + assert.Equal(t, types.String.Size(), 8) assert.Equal(t, (&types.Pointer{To: types.Int}).Size(), 8) } @@ -37,7 +40,7 @@ func TestStruct(t *testing.T) { func TestBasics(t *testing.T) { assert.True(t, types.Is(types.Int, types.Int)) - assert.True(t, types.Is(types.PointerAny, types.PointerAny)) + assert.True(t, types.Is(types.AnyPointer, types.AnyPointer)) assert.False(t, types.Is(types.Int, types.Float)) assert.False(t, types.Is(&types.Pointer{To: types.Int}, &types.Pointer{To: types.Float})) } @@ -50,6 +53,7 @@ func TestSpecialCases(t *testing.T) { // Case #2: // A pointer pointing to a known type fulfills the requirement of a pointer to anything. - assert.True(t, types.Is(&types.Pointer{To: types.Int}, &types.Pointer{To: nil})) - assert.True(t, types.Is(&types.Pointer{To: types.Float}, &types.Pointer{To: nil})) + assert.True(t, types.Is(&types.Pointer{To: types.Int}, types.AnyPointer)) + assert.True(t, types.Is(&types.Pointer{To: types.Float}, types.AnyPointer)) + assert.True(t, types.Is(&types.Array{Of: types.Int}, types.AnyPointer)) }