Added placeholders for type casts

This commit is contained in:
Eduard Urbach 2025-02-27 00:18:34 +01:00
parent bbf2970c4e
commit ae6530aadb
Signed by: akyoto
GPG Key ID: C874F672B1AF20C0
19 changed files with 61 additions and 42 deletions

View File

@ -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 io
import net import net
import sys import sys

View File

@ -1,6 +1,6 @@
import sys import sys
bind(socket int, port int) -> int { bind(socket int, port uint16) -> int {
addr := new(sys.sockaddr_in) addr := new(sys.sockaddr_in)
addr.sin_family = 2 addr.sin_family = 2
addr.sin_port = htons(port) addr.sin_port = htons(port)

View File

@ -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) fd = kernel32.GetStdHandle(-10 - fd)
kernel32.ReadConsole(fd, buffer, length, 0) kernel32.ReadConsole(fd, buffer, uint32(length), 0)
return length return length
} }
write(fd int64, buffer *byte, length int64) -> int64 { write(fd int, buffer *byte, length int) -> int {
fd = kernel32.GetStdHandle(-10 - fd) fd = kernel32.GetStdHandle(-10 - fd)
kernel32.WriteConsoleA(fd, buffer, length, 0) kernel32.WriteConsoleA(fd, buffer, uint32(length), 0)
return length return length
} }

View File

@ -12,10 +12,8 @@ const clone {
} }
create(func *any) -> int { create(func *any) -> int {
size := 4096 stack := sys.mmap(0, 4096, 0x1|0x2, 0x02|0x20|0x100)
stack := sys.mmap(0, size, 0x1|0x2, 0x02|0x20|0x100|0x20000) stack += 4096 - 8
stack += size
stack -= 8
store(stack, 8, core.exit) store(stack, 8, core.exit)
stack -= 8 stack -= 8
store(stack, 8, func) store(stack, 8, func)

View File

@ -50,8 +50,8 @@ func (f *Function) ArrayElementToRegister(node *expression.Expression, register
defer f.UseVariable(indexVariable) defer f.UseVariable(indexVariable)
if !types.Is(indexVariable.Type, types.Int) { if !types.Is(indexVariable.Type, types.AnyInt) {
return nil, errors.New(&errors.TypeMismatch{Encountered: indexVariable.Type.Name(), Expected: types.Int.Name()}, f.File, index.Token.Position) return nil, errors.New(&errors.TypeMismatch{Encountered: indexVariable.Type.Name(), Expected: types.AnyInt.Name()}, f.File, index.Token.Position)
} }
memory.OffsetRegister = indexVariable.Register memory.OffsetRegister = indexVariable.Register
@ -63,8 +63,8 @@ func (f *Function) ArrayElementToRegister(node *expression.Expression, register
return nil, err return nil, err
} }
if !types.Is(typ, types.Int) { if !types.Is(typ, types.AnyInt) {
return nil, errors.New(&errors.TypeMismatch{Encountered: typ.Name(), Expected: types.Int.Name()}, f.File, index.Token.Position) return nil, errors.New(&errors.TypeMismatch{Encountered: typ.Name(), Expected: types.AnyInt.Name()}, f.File, index.Token.Position)
} }
memory.OffsetRegister = register memory.OffsetRegister = register

View File

@ -47,8 +47,8 @@ func (f *Function) CompileAssignArray(node *ast.Assign) error {
return err return err
} }
if !types.Is(typ, types.Int) { if !types.Is(typ, types.AnyInt) {
return errors.New(&errors.TypeMismatch{Encountered: typ.Name(), Expected: types.Int.Name()}, f.File, index.Token.Position) return errors.New(&errors.TypeMismatch{Encountered: typ.Name(), Expected: types.AnyInt.Name()}, f.File, index.Token.Position)
} }
memory.OffsetRegister = indexRegister memory.OffsetRegister = indexRegister

View File

@ -52,6 +52,17 @@ func (f *Function) CompileCall(root *expression.Expression) ([]types.Type, error
fn, exists = f.All.Functions[pkg+"."+name] fn, exists = f.All.Functions[pkg+"."+name]
if !exists { 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) return nil, errors.New(&errors.UnknownFunction{Name: name}, f.File, nameNode.Token.Position)
} }

View File

@ -6,6 +6,7 @@ import (
"git.urbach.dev/cli/q/src/errors" "git.urbach.dev/cli/q/src/errors"
"git.urbach.dev/cli/q/src/expression" "git.urbach.dev/cli/q/src/expression"
"git.urbach.dev/cli/q/src/token" "git.urbach.dev/cli/q/src/token"
"git.urbach.dev/cli/q/src/types"
) )
// CompileDefinition compiles a variable definition. // 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()) return errors.New(errors.UntypedExpression, f.File, node.Expression.Token.End())
} }
if typ == types.AnyInt {
typ = types.Int
}
variable.Type = typ variable.Type = typ
f.AddVariable(variable) f.AddVariable(variable)
return nil return nil

View File

@ -9,7 +9,7 @@ import (
"git.urbach.dev/cli/q/src/types" "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. // CompileLen returns the length of a slice.
func (f *Function) CompileLen(root *expression.Expression) error { func (f *Function) CompileLen(root *expression.Expression) error {

View File

@ -48,7 +48,7 @@ func (f *Function) ExpressionToMemory(node *expression.Expression, memory asm.Me
// } // }
f.MemoryNumber(asm.STORE, memory, number) f.MemoryNumber(asm.STORE, memory, number)
return types.Int, nil return types.AnyInt, nil
} }
} }

View File

@ -13,7 +13,7 @@ import (
func (f *Function) ExpressionToRegister(node *expression.Expression, register cpu.Register) (types.Type, error) { func (f *Function) ExpressionToRegister(node *expression.Expression, register cpu.Register) (types.Type, error) {
if node.IsFolded { if node.IsFolded {
f.RegisterNumber(asm.MOVE, register, node.Value) f.RegisterNumber(asm.MOVE, register, node.Value)
return types.Int, nil return types.AnyInt, nil
} }
if node.IsLeaf() { if node.IsLeaf() {

View File

@ -14,8 +14,8 @@ import (
// PeriodToRegister moves a constant or a function address into the given register. // 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) { func (f *Function) PeriodToRegister(node *expression.Expression, register cpu.Register) (types.Type, error) {
left := node.Children[0] left := node.Children[0]
leftText := left.Token.Text(f.File.Bytes)
right := node.Children[1] right := node.Children[1]
leftText := left.Token.Text(f.File.Bytes)
rightText := right.Token.Text(f.File.Bytes) rightText := right.Token.Text(f.File.Bytes)
variable := f.VariableByName(leftText) variable := f.VariableByName(leftText)
@ -44,7 +44,7 @@ func (f *Function) PeriodToRegister(node *expression.Expression, register cpu.Re
f.SaveRegister(register) f.SaveRegister(register)
f.RegisterNumber(asm.MOVE, register, number) f.RegisterNumber(asm.MOVE, register, number)
return types.Int, nil return types.AnyInt, nil
} }
uniqueName := fmt.Sprintf("%s.%s", leftText, rightText) uniqueName := fmt.Sprintf("%s.%s", leftText, rightText)

View File

@ -53,7 +53,7 @@ func (f *Function) TokenToRegister(t token.Token, register cpu.Register) (types.
f.SaveRegister(register) f.SaveRegister(register)
f.RegisterNumber(asm.MOVE, register, number) f.RegisterNumber(asm.MOVE, register, number)
return types.Int, nil return types.AnyInt, nil
case token.String: case token.String:
data := t.Bytes(f.File.Bytes) data := t.Bytes(f.File.Bytes)

View File

@ -3,6 +3,7 @@ package types
var ( var (
Any = &Base{name: "any", size: 0} Any = &Base{name: "any", size: 0}
AnyArray = &Array{Of: Any} AnyArray = &Array{Of: Any}
AnyInt = &Base{name: "int"}
AnyPointer = &Pointer{To: Any} AnyPointer = &Pointer{To: Any}
Bool = &Base{name: "bool", size: 1} Bool = &Base{name: "bool", size: 1}
Int64 = &Base{name: "int64", size: 8} Int64 = &Base{name: "int64", size: 8}
@ -12,15 +13,15 @@ var (
Float64 = &Base{name: "float64", size: 8} Float64 = &Base{name: "float64", size: 8}
Float32 = &Base{name: "float32", size: 4} Float32 = &Base{name: "float32", size: 4}
String = &Array{Of: Byte} 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 ( var (
Byte = UInt8 Byte = UInt8
Int = Int64
Float = Float64 Float = Float64
UInt = Int Int = Int64
UInt64 = Int64 UInt = UInt64
UInt32 = Int32
UInt16 = Int16
UInt8 = Int8
) )

View File

@ -25,13 +25,11 @@ func Is(a Type, b Type) bool {
return true return true
} }
// Temporary hacks if a == AnyInt {
if a == Int32 && b == Int64 { switch b {
case Int64, Int32, Int16, Int8, UInt64, UInt32, UInt16, UInt8:
return true return true
} }
if a == Int64 && b == Int32 {
return true
} }
return false return false

View File

@ -13,7 +13,7 @@ func TestName(t *testing.T) {
assert.Equal(t, types.AnyPointer.Name(), "*any") assert.Equal(t, types.AnyPointer.Name(), "*any")
assert.Equal(t, (&types.Pointer{To: types.Int}).Name(), "*int64") assert.Equal(t, (&types.Pointer{To: types.Int}).Name(), "*int64")
assert.Equal(t, (&types.Array{Of: 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) { func TestSize(t *testing.T) {

View File

@ -50,8 +50,8 @@ var errs = []struct {
{"MissingParameter3.q", errors.MissingParameter}, {"MissingParameter3.q", errors.MissingParameter},
{"MissingType.q", errors.MissingType}, {"MissingType.q", errors.MissingType},
{"ReturnCountMismatch.q", &errors.ReturnCountMismatch{Count: 1, ExpectedCount: 0}}, {"ReturnCountMismatch.q", &errors.ReturnCountMismatch{Count: 1, ExpectedCount: 0}},
{"TypeMismatch.q", &errors.TypeMismatch{Expected: "*any", Encountered: "int64", ParameterName: "p"}}, {"TypeMismatch.q", &errors.TypeMismatch{Expected: "*any", Encountered: "int", ParameterName: "p"}},
{"TypeMismatch2.q", &errors.TypeMismatch{Expected: "[]any", Encountered: "int64", ParameterName: "array"}}, {"TypeMismatch2.q", &errors.TypeMismatch{Expected: "[]any", Encountered: "int", ParameterName: "array"}},
{"UnknownFunction.q", &errors.UnknownFunction{Name: "unknown"}}, {"UnknownFunction.q", &errors.UnknownFunction{Name: "unknown"}},
{"UnknownFunction2.q", &errors.UnknownFunction{Name: "f"}}, {"UnknownFunction2.q", &errors.UnknownFunction{Name: "f"}},
{"UnknownIdentifier.q", &errors.UnknownIdentifier{Name: "x"}}, {"UnknownIdentifier.q", &errors.UnknownIdentifier{Name: "x"}},

8
tests/programs/cast.q Normal file
View File

@ -0,0 +1,8 @@
main() {
x := byte(42)
assert f(x) == 42
}
f(x byte) -> byte {
return x
}

View File

@ -67,6 +67,7 @@ var programs = []struct {
{"index-dynamic", 0}, {"index-dynamic", 0},
{"struct", 0}, {"struct", 0},
{"len", 0}, {"len", 0},
{"cast", 0},
} }
func TestPrograms(t *testing.T) { func TestPrograms(t *testing.T) {