diff --git a/examples/server/server.q b/examples/server/server.q index 6ac4ee3..f90c1c7 100644 --- a/examples/server/server.q +++ b/examples/server/server.q @@ -1,6 +1,3 @@ -// Open server and client in 2 terminals: -// [1] q run examples/server -// [2] curl http://127.0.0.1:8080 import io import net import sys diff --git a/lib/net/net_linux.q b/lib/net/net_linux.q index 4a025e3..168c8a2 100644 --- a/lib/net/net_linux.q +++ b/lib/net/net_linux.q @@ -1,6 +1,6 @@ import sys -bind(socket int, port int) -> int { +bind(socket int, port uint16) -> int { addr := new(sys.sockaddr_in) addr.sin_family = 2 addr.sin_port = htons(port) diff --git a/lib/sys/sys_windows.q b/lib/sys/sys_windows.q index 2523338..59e6769 100644 --- a/lib/sys/sys_windows.q +++ b/lib/sys/sys_windows.q @@ -1,12 +1,12 @@ -read(fd int64, buffer *byte, length int64) -> int64 { +read(fd int, buffer *byte, length int) -> int { fd = kernel32.GetStdHandle(-10 - fd) - kernel32.ReadConsole(fd, buffer, length, 0) + kernel32.ReadConsole(fd, buffer, uint32(length), 0) return length } -write(fd int64, buffer *byte, length int64) -> int64 { +write(fd int, buffer *byte, length int) -> int { fd = kernel32.GetStdHandle(-10 - fd) - kernel32.WriteConsoleA(fd, buffer, length, 0) + kernel32.WriteConsoleA(fd, buffer, uint32(length), 0) return length } diff --git a/lib/thread/thread_linux.q b/lib/thread/thread_linux.q index cf4d75a..592207b 100644 --- a/lib/thread/thread_linux.q +++ b/lib/thread/thread_linux.q @@ -12,10 +12,8 @@ const clone { } create(func *any) -> int { - size := 4096 - stack := sys.mmap(0, size, 0x1|0x2, 0x02|0x20|0x100|0x20000) - stack += size - stack -= 8 + stack := sys.mmap(0, 4096, 0x1|0x2, 0x02|0x20|0x100) + stack += 4096 - 8 store(stack, 8, core.exit) stack -= 8 store(stack, 8, func) diff --git a/src/core/ArrayElementToRegister.go b/src/core/ArrayElementToRegister.go index 0dec215..9e58f3e 100644 --- a/src/core/ArrayElementToRegister.go +++ b/src/core/ArrayElementToRegister.go @@ -50,8 +50,8 @@ func (f *Function) ArrayElementToRegister(node *expression.Expression, register defer f.UseVariable(indexVariable) - if !types.Is(indexVariable.Type, types.Int) { - return nil, errors.New(&errors.TypeMismatch{Encountered: indexVariable.Type.Name(), Expected: types.Int.Name()}, f.File, index.Token.Position) + if !types.Is(indexVariable.Type, types.AnyInt) { + return nil, errors.New(&errors.TypeMismatch{Encountered: indexVariable.Type.Name(), Expected: types.AnyInt.Name()}, f.File, index.Token.Position) } memory.OffsetRegister = indexVariable.Register @@ -63,8 +63,8 @@ func (f *Function) ArrayElementToRegister(node *expression.Expression, register return nil, err } - if !types.Is(typ, types.Int) { - return nil, errors.New(&errors.TypeMismatch{Encountered: typ.Name(), Expected: types.Int.Name()}, f.File, index.Token.Position) + if !types.Is(typ, types.AnyInt) { + return nil, errors.New(&errors.TypeMismatch{Encountered: typ.Name(), Expected: types.AnyInt.Name()}, f.File, index.Token.Position) } memory.OffsetRegister = register diff --git a/src/core/CompileAssignArray.go b/src/core/CompileAssignArray.go index 55e33a5..fff34ca 100644 --- a/src/core/CompileAssignArray.go +++ b/src/core/CompileAssignArray.go @@ -47,8 +47,8 @@ func (f *Function) CompileAssignArray(node *ast.Assign) error { return err } - if !types.Is(typ, types.Int) { - return errors.New(&errors.TypeMismatch{Encountered: typ.Name(), Expected: types.Int.Name()}, f.File, index.Token.Position) + if !types.Is(typ, types.AnyInt) { + return errors.New(&errors.TypeMismatch{Encountered: typ.Name(), Expected: types.AnyInt.Name()}, f.File, index.Token.Position) } memory.OffsetRegister = indexRegister diff --git a/src/core/CompileCall.go b/src/core/CompileCall.go index 3d4ad40..e9c94b2 100644 --- a/src/core/CompileCall.go +++ b/src/core/CompileCall.go @@ -52,6 +52,17 @@ func (f *Function) CompileCall(root *expression.Expression) ([]types.Type, error fn, exists = f.All.Functions[pkg+"."+name] if !exists { + typ := types.ByName(name, f.Package, f.All.Structs) + + if typ != nil { + if len(root.Children) != 2 { + return nil, errors.New(&errors.ParameterCountMismatch{Function: name, Count: len(root.Children), ExpectedCount: 1}, f.File, nameNode.Token.End()) + } + + _, err := f.ExpressionToRegister(root.Children[1], f.CPU.Output[0]) + return []types.Type{typ}, err + } + return nil, errors.New(&errors.UnknownFunction{Name: name}, f.File, nameNode.Token.Position) } diff --git a/src/core/CompileDefinition.go b/src/core/CompileDefinition.go index 71d4b73..af96b46 100644 --- a/src/core/CompileDefinition.go +++ b/src/core/CompileDefinition.go @@ -6,6 +6,7 @@ import ( "git.urbach.dev/cli/q/src/errors" "git.urbach.dev/cli/q/src/expression" "git.urbach.dev/cli/q/src/token" + "git.urbach.dev/cli/q/src/types" ) // CompileDefinition compiles a variable definition. @@ -30,6 +31,10 @@ func (f *Function) CompileDefinition(node *ast.Define) error { return errors.New(errors.UntypedExpression, f.File, node.Expression.Token.End()) } + if typ == types.AnyInt { + typ = types.Int + } + variable.Type = typ f.AddVariable(variable) return nil diff --git a/src/core/CompileLen.go b/src/core/CompileLen.go index 4065d76..4571c38 100644 --- a/src/core/CompileLen.go +++ b/src/core/CompileLen.go @@ -9,7 +9,7 @@ import ( "git.urbach.dev/cli/q/src/types" ) -var _len = Function{OutputTypes: []types.Type{types.Int}} +var _len = Function{OutputTypes: []types.Type{types.AnyInt}} // CompileLen returns the length of a slice. func (f *Function) CompileLen(root *expression.Expression) error { diff --git a/src/core/ExpressionToMemory.go b/src/core/ExpressionToMemory.go index f62ba58..8886f6e 100644 --- a/src/core/ExpressionToMemory.go +++ b/src/core/ExpressionToMemory.go @@ -48,7 +48,7 @@ func (f *Function) ExpressionToMemory(node *expression.Expression, memory asm.Me // } f.MemoryNumber(asm.STORE, memory, number) - return types.Int, nil + return types.AnyInt, nil } } diff --git a/src/core/ExpressionToRegister.go b/src/core/ExpressionToRegister.go index 0a3fb29..54d82b2 100644 --- a/src/core/ExpressionToRegister.go +++ b/src/core/ExpressionToRegister.go @@ -13,7 +13,7 @@ import ( func (f *Function) ExpressionToRegister(node *expression.Expression, register cpu.Register) (types.Type, error) { if node.IsFolded { f.RegisterNumber(asm.MOVE, register, node.Value) - return types.Int, nil + return types.AnyInt, nil } if node.IsLeaf() { diff --git a/src/core/PeriodToRegister.go b/src/core/PeriodToRegister.go index 2307a43..aeb7675 100644 --- a/src/core/PeriodToRegister.go +++ b/src/core/PeriodToRegister.go @@ -14,8 +14,8 @@ import ( // PeriodToRegister moves a constant or a function address into the given register. func (f *Function) PeriodToRegister(node *expression.Expression, register cpu.Register) (types.Type, error) { left := node.Children[0] - leftText := left.Token.Text(f.File.Bytes) right := node.Children[1] + leftText := left.Token.Text(f.File.Bytes) rightText := right.Token.Text(f.File.Bytes) variable := f.VariableByName(leftText) @@ -44,7 +44,7 @@ func (f *Function) PeriodToRegister(node *expression.Expression, register cpu.Re f.SaveRegister(register) f.RegisterNumber(asm.MOVE, register, number) - return types.Int, nil + return types.AnyInt, nil } uniqueName := fmt.Sprintf("%s.%s", leftText, rightText) diff --git a/src/core/TokenToRegister.go b/src/core/TokenToRegister.go index e05d9e8..fce74e1 100644 --- a/src/core/TokenToRegister.go +++ b/src/core/TokenToRegister.go @@ -53,7 +53,7 @@ func (f *Function) TokenToRegister(t token.Token, register cpu.Register) (types. f.SaveRegister(register) f.RegisterNumber(asm.MOVE, register, number) - return types.Int, nil + return types.AnyInt, nil case token.String: data := t.Bytes(f.File.Bytes) diff --git a/src/types/Common.go b/src/types/Common.go index 8cab280..124a6bc 100644 --- a/src/types/Common.go +++ b/src/types/Common.go @@ -3,6 +3,7 @@ package types var ( Any = &Base{name: "any", size: 0} AnyArray = &Array{Of: Any} + AnyInt = &Base{name: "int"} AnyPointer = &Pointer{To: Any} Bool = &Base{name: "bool", size: 1} Int64 = &Base{name: "int64", size: 8} @@ -12,15 +13,15 @@ var ( Float64 = &Base{name: "float64", size: 8} Float32 = &Base{name: "float32", size: 4} String = &Array{Of: Byte} + UInt64 = &Base{name: "uint64", size: 8} + UInt32 = &Base{name: "uint32", size: 4} + UInt16 = &Base{name: "uint16", size: 2} + UInt8 = &Base{name: "uint8", size: 1} ) var ( - Byte = UInt8 - Int = Int64 - Float = Float64 - UInt = Int - UInt64 = Int64 - UInt32 = Int32 - UInt16 = Int16 - UInt8 = Int8 + Byte = UInt8 + Float = Float64 + Int = Int64 + UInt = UInt64 ) diff --git a/src/types/Is.go b/src/types/Is.go index 1629454..875df1a 100644 --- a/src/types/Is.go +++ b/src/types/Is.go @@ -25,13 +25,11 @@ func Is(a Type, b Type) bool { return true } - // Temporary hacks - if a == Int32 && b == Int64 { - return true - } - - if a == Int64 && b == Int32 { - return true + if a == AnyInt { + switch b { + case Int64, Int32, Int16, Int8, UInt64, UInt32, UInt16, UInt8: + return true + } } return false diff --git a/src/types/types_test.go b/src/types/types_test.go index 856c878..e43bcee 100644 --- a/src/types/types_test.go +++ b/src/types/types_test.go @@ -13,7 +13,7 @@ func TestName(t *testing.T) { assert.Equal(t, types.AnyPointer.Name(), "*any") 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") + assert.Equal(t, types.String.Name(), "[]uint8") } func TestSize(t *testing.T) { diff --git a/tests/errors_test.go b/tests/errors_test.go index 6b10e3f..e672684 100644 --- a/tests/errors_test.go +++ b/tests/errors_test.go @@ -50,8 +50,8 @@ 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: "int64", ParameterName: "p"}}, - {"TypeMismatch2.q", &errors.TypeMismatch{Expected: "[]any", Encountered: "int64", ParameterName: "array"}}, + {"TypeMismatch.q", &errors.TypeMismatch{Expected: "*any", Encountered: "int", ParameterName: "p"}}, + {"TypeMismatch2.q", &errors.TypeMismatch{Expected: "[]any", Encountered: "int", ParameterName: "array"}}, {"UnknownFunction.q", &errors.UnknownFunction{Name: "unknown"}}, {"UnknownFunction2.q", &errors.UnknownFunction{Name: "f"}}, {"UnknownIdentifier.q", &errors.UnknownIdentifier{Name: "x"}}, diff --git a/tests/programs/cast.q b/tests/programs/cast.q new file mode 100644 index 0000000..8eb8ae4 --- /dev/null +++ b/tests/programs/cast.q @@ -0,0 +1,8 @@ +main() { + x := byte(42) + assert f(x) == 42 +} + +f(x byte) -> byte { + return x +} \ No newline at end of file diff --git a/tests/programs_test.go b/tests/programs_test.go index 2650a88..2f15d5f 100644 --- a/tests/programs_test.go +++ b/tests/programs_test.go @@ -67,6 +67,7 @@ var programs = []struct { {"index-dynamic", 0}, {"struct", 0}, {"len", 0}, + {"cast", 0}, } func TestPrograms(t *testing.T) {