diff --git a/examples/collatz/collatz.q b/examples/collatz/collatz.q index 32507a4..f7d9037 100644 --- a/examples/collatz/collatz.q +++ b/examples/collatz/collatz.q @@ -5,7 +5,7 @@ main() { collatz(12) } -collatz(x) { +collatz(x Int) { loop { if x & 1 == 0 { x /= 2 diff --git a/examples/factorial/factorial.q b/examples/factorial/factorial.q index dab665c..885fc2f 100644 --- a/examples/factorial/factorial.q +++ b/examples/factorial/factorial.q @@ -4,7 +4,7 @@ main() { log.number(factorial(5)) } -factorial(x) { +factorial(x Int) -> Int { if x <= 1 { return 1 } diff --git a/examples/fibonacci/fibonacci.q b/examples/fibonacci/fibonacci.q index acc3e78..a071002 100644 --- a/examples/fibonacci/fibonacci.q +++ b/examples/fibonacci/fibonacci.q @@ -4,7 +4,7 @@ main() { log.number(fibonacci(10)) } -fibonacci(x) { +fibonacci(x Int) -> Int { if x <= 1 { return x } diff --git a/examples/fizzbuzz/fizzbuzz.q b/examples/fizzbuzz/fizzbuzz.q index 9d88215..5cca2d5 100644 --- a/examples/fizzbuzz/fizzbuzz.q +++ b/examples/fizzbuzz/fizzbuzz.q @@ -5,7 +5,7 @@ main() { fizzbuzz(15) } -fizzbuzz(n) { +fizzbuzz(n Int) { x := 1 loop { @@ -26,6 +26,6 @@ fizzbuzz(n) { } } -print(address, length) { +print(address Pointer, length Int) { sys.write(1, address, length) } \ No newline at end of file diff --git a/examples/gcd/gcd.q b/examples/gcd/gcd.q index 03dead2..d952825 100644 --- a/examples/gcd/gcd.q +++ b/examples/gcd/gcd.q @@ -4,7 +4,7 @@ main() { log.number(gcd(1071, 462)) } -gcd(a, b) { +gcd(a Int, b Int) -> Int { loop { switch { a == b { return a } diff --git a/examples/hello/hello.q b/examples/hello/hello.q index 2371295..1d9220d 100644 --- a/examples/hello/hello.q +++ b/examples/hello/hello.q @@ -4,6 +4,6 @@ main() { print("Hello\n", 6) } -print(address, length) { +print(address Pointer, length Int) { sys.write(1, address, length) } \ No newline at end of file diff --git a/examples/prime/prime.q b/examples/prime/prime.q index a117bdc..836c831 100644 --- a/examples/prime/prime.q +++ b/examples/prime/prime.q @@ -22,7 +22,7 @@ main() { } } -isPrime(x) { +isPrime(x Int) -> Int { if x == 2 { return 1 } diff --git a/lib/log/number.q b/lib/log/number.q index 86be427..93b7388 100644 --- a/lib/log/number.q +++ b/lib/log/number.q @@ -1,7 +1,7 @@ import mem import sys -number(x) { +number(x Int) { length := 20 buffer := mem.alloc(length) address, count := itoa(x, buffer, length) @@ -9,7 +9,7 @@ number(x) { mem.free(buffer, length) } -itoa(x, buffer, length) { +itoa(x Int, buffer Pointer, length Int) -> (Pointer, Int) { end := buffer + length tmp := end digit := 0 diff --git a/lib/mem/alloc.q b/lib/mem/alloc.q index 3a6347c..747290a 100644 --- a/lib/mem/alloc.q +++ b/lib/mem/alloc.q @@ -1,9 +1,9 @@ import sys -alloc(length) { +alloc(length Int) -> Pointer { return sys.mmap(0, length, 0x1|0x2, 0x02|0x20|0x100) } -free(address, length) { +free(address Pointer, length Int) -> Int { return sys.munmap(address, length) } \ No newline at end of file diff --git a/lib/sys/linux.q b/lib/sys/linux.q index d582d1c..e6d84c2 100644 --- a/lib/sys/linux.q +++ b/lib/sys/linux.q @@ -1,71 +1,71 @@ -read(fd, address, length) { +read(fd Int, address Pointer, length Int) -> Int { return syscall(0, fd, address, length) } -write(fd, address, length) { +write(fd Int, address Pointer, length Int) -> Int { return syscall(1, fd, address, length) } -open(file, flags, mode) { +open(file Pointer, flags Int, mode Int) -> Int { return syscall(2, file, flags, mode) } -close(fd) { +close(fd Int) -> Int { return syscall(3, fd) } -mmap(address, length, protection, flags) { +mmap(address Int, length Int, protection Int, flags Int) -> Int { return syscall(9, address, length, protection, flags) } -munmap(address, length) { +munmap(address Pointer, length Int) -> Int { return syscall(11, address, length) } -clone(flags, stack) { +clone(flags Int, stack Pointer) -> ThreadID { return syscall(56, flags, stack) } -exit(code) { - syscall(60, code) +exit(status Int) { + syscall(60, status) } -socket(family, type, protocol) { +socket(family Int, type Int, protocol Int) -> Int { return syscall(41, family, type, protocol) } -accept(fd, address, length) { +accept(fd Int, address Pointer, length Int) -> Int { return syscall(43, fd, address, length) } -bind(fd, address, length) { +bind(fd Int, address Pointer, length Int) -> Int { return syscall(49, fd, address, length) } -listen(fd, backlog) { +listen(fd Int, backlog Int) -> Int { return syscall(50, fd, backlog) } -getcwd(buffer, length) { +getcwd(buffer Pointer, length Int) -> Int { return syscall(79, buffer, length) } -chdir(path) { +chdir(path Pointer) -> Int { return syscall(80, path) } -rename(old, new) { +rename(old Pointer, new Pointer) -> Int { return syscall(82, old, new) } -mkdir(path, mode) { +mkdir(path Pointer, mode Int) -> Int { return syscall(83, path, mode) } -rmdir(path) { +rmdir(path Pointer) -> Int { return syscall(84, path) } -unlink(file) { +unlink(file Pointer) -> Int { return syscall(87, file) } diff --git a/src/build/errors/Base.go b/src/build/errors/Base.go index a019d58..136c9bf 100644 --- a/src/build/errors/Base.go +++ b/src/build/errors/Base.go @@ -1,5 +1,26 @@ package errors +var ( + EmptySwitch = &Base{"Empty switch"} + ExpectedFunctionName = &Base{"Expected function name"} + ExpectedFunctionParameters = &Base{"Expected function parameters"} + ExpectedFunctionDefinition = &Base{"Expected function definition"} + ExpectedIfBeforeElse = &Base{"Expected an 'if' block before 'else'"} + InvalidNumber = &Base{"Invalid number"} + InvalidExpression = &Base{"Invalid expression"} + InvalidRune = &Base{"Invalid rune"} + InvalidStatement = &Base{"Invalid statement"} + MissingBlockStart = &Base{"Missing '{'"} + MissingBlockEnd = &Base{"Missing '}'"} + MissingExpression = &Base{"Missing expression"} + MissingGroupStart = &Base{"Missing '('"} + MissingGroupEnd = &Base{"Missing ')'"} + MissingMainFunction = &Base{"Missing main function"} + MissingOperand = &Base{"Missing operand"} + MissingType = &Base{"Missing type"} + NotImplemented = &Base{"Not implemented"} +) + // Base is the base class for errors that have no parameters. type Base struct { Message string diff --git a/src/build/errors/CompileErrors.go b/src/build/errors/CompileErrors.go deleted file mode 100644 index c0e14cb..0000000 --- a/src/build/errors/CompileErrors.go +++ /dev/null @@ -1,14 +0,0 @@ -package errors - -var ( - EmptySwitch = &Base{"Empty switch"} - ExpectedIfBeforeElse = &Base{"Expected an 'if' block before 'else'"} - InvalidNumber = &Base{"Invalid number"} - InvalidExpression = &Base{"Invalid expression"} - InvalidRune = &Base{"Invalid rune"} - InvalidStatement = &Base{"Invalid statement"} - MissingExpression = &Base{"Missing expression"} - MissingMainFunction = &Base{"Missing main function"} - MissingOperand = &Base{"Missing operand"} - NotImplemented = &Base{"Not implemented"} -) diff --git a/src/build/errors/ScanErrors.go b/src/build/errors/ScanErrors.go deleted file mode 100644 index 7fe07f2..0000000 --- a/src/build/errors/ScanErrors.go +++ /dev/null @@ -1,11 +0,0 @@ -package errors - -var ( - MissingBlockStart = &Base{"Missing '{'"} - MissingBlockEnd = &Base{"Missing '}'"} - MissingGroupStart = &Base{"Missing '('"} - MissingGroupEnd = &Base{"Missing ')'"} - ExpectedFunctionName = &Base{"Expected function name"} - ExpectedFunctionParameters = &Base{"Expected function parameters"} - ExpectedFunctionDefinition = &Base{"Expected function definition"} -) diff --git a/src/build/scanner/scanFile.go b/src/build/scanner/scanFile.go index 0f21732..59260bd 100644 --- a/src/build/scanner/scanFile.go +++ b/src/build/scanner/scanFile.go @@ -1,6 +1,7 @@ package scanner import ( + "fmt" "os" "path/filepath" @@ -153,8 +154,20 @@ func (s *Scanner) scanFile(path string, pkg string) error { return errors.New(errors.ExpectedFunctionParameters, file, tokens[i].Position) } + // Return type + if i < len(tokens) && tokens[i].Kind == token.ReturnType { + for i < len(tokens) && tokens[i].Kind != token.BlockStart { + i++ + } + } + // Function definition for i < len(tokens) { + if tokens[i].Kind == token.ReturnType { + i++ + continue + } + if tokens[i].Kind == token.BlockStart { blockLevel++ i++ @@ -207,17 +220,18 @@ func (s *Scanner) scanFile(path string, pkg string) error { name := tokens[nameStart].Text(contents) body := tokens[bodyStart:i] - function := core.NewFunction(pkg, name, file, body) parameters := tokens[paramsStart:paramsEnd] count := 0 err := expression.EachParameter(parameters, func(tokens token.List) error { - if len(tokens) != 1 { - return errors.New(errors.NotImplemented, file, tokens[0].Position) + if len(tokens) < 2 { + return errors.New(errors.MissingType, file, tokens[0].End()) } name := tokens[0].Text(contents) + dataType := tokens[1].Text(contents) + fmt.Println(dataType) register := x64.CallRegisters[count] uses := token.Count(function.Body, contents, token.Identifier, name) diff --git a/src/build/token/Kind.go b/src/build/token/Kind.go index fa97224..e0c23f8 100644 --- a/src/build/token/Kind.go +++ b/src/build/token/Kind.go @@ -18,6 +18,7 @@ const ( BlockEnd // } ArrayStart // [ ArrayEnd // ] + ReturnType // -> _operators // Add // + Sub // - diff --git a/src/build/token/Tokenize.go b/src/build/token/Tokenize.go index 85d3eba..2e15e25 100644 --- a/src/build/token/Tokenize.go +++ b/src/build/token/Tokenize.go @@ -30,9 +30,17 @@ func Tokenize(buffer []byte) List { if len(tokens) == 0 || tokens[len(tokens)-1].IsOperator() || tokens[len(tokens)-1].IsExpressionStart() || tokens[len(tokens)-1].IsKeyword() { tokens = append(tokens, Token{Kind: Negate, Position: i, Length: 1}) } else { - if i+1 < Position(len(buffer)) && buffer[i+1] == '=' { - tokens = append(tokens, Token{Kind: SubAssign, Position: i, Length: 2}) - i++ + if i+1 < Position(len(buffer)) { + switch buffer[i+1] { + case '=': + tokens = append(tokens, Token{Kind: SubAssign, Position: i, Length: 2}) + i++ + case '>': + tokens = append(tokens, Token{Kind: ReturnType, Position: i, Length: 2}) + i++ + default: + tokens = append(tokens, Token{Kind: Sub, Position: i, Length: 1}) + } } else { tokens = append(tokens, Token{Kind: Sub, Position: i, Length: 1}) } @@ -212,10 +220,12 @@ func Tokenize(buffer []byte) List { kind = Add case "+=": kind = AddAssign - case "-": - kind = Sub - case "-=": - kind = SubAssign + // case "-": + // kind = Sub + // case "-=": + // kind = SubAssign + // case "->": + // kind = ReturnType case ".": kind = Period case "/": diff --git a/tests/errors/UnknownIdentifier3.q b/tests/errors/UnknownIdentifier3.q index a7387e2..4cc4927 100644 --- a/tests/errors/UnknownIdentifier3.q +++ b/tests/errors/UnknownIdentifier3.q @@ -2,6 +2,6 @@ main() { x := 1 + f(x) } -f(x) { +f(x Int) -> Int { return x } \ No newline at end of file diff --git a/tests/programs/branch.q b/tests/programs/branch.q index 9e6f514..171002b 100644 --- a/tests/programs/branch.q +++ b/tests/programs/branch.q @@ -70,14 +70,14 @@ main() { if x == 0 { sys.exit(0) } - + sys.exit(1) } -inc(x) { +inc(x Int) -> Int { return x + 1 } -dec(x) { +dec(x Int) -> Int { return x - 1 } \ No newline at end of file diff --git a/tests/programs/chained-calls.q b/tests/programs/chained-calls.q index e62a02e..cd3c519 100644 --- a/tests/programs/chained-calls.q +++ b/tests/programs/chained-calls.q @@ -2,6 +2,6 @@ main() { assert f(1) + f(2) + f(3) == 9 } -f(x) { +f(x Int) -> Int { return x + 1 } \ No newline at end of file diff --git a/tests/programs/64-bit.q b/tests/programs/int64.q similarity index 100% rename from tests/programs/64-bit.q rename to tests/programs/int64.q diff --git a/tests/programs/loop-lifetime.q b/tests/programs/loop-lifetime.q index 1262b7d..d30489e 100644 --- a/tests/programs/loop-lifetime.q +++ b/tests/programs/loop-lifetime.q @@ -12,6 +12,6 @@ main() { } } -f(x) { +f(x Int) -> Int { return x } \ No newline at end of file diff --git a/tests/programs/math.q b/tests/programs/math.q index 6fd1712..2de1b1b 100644 --- a/tests/programs/math.q +++ b/tests/programs/math.q @@ -4,10 +4,10 @@ main() { assert result == 10 } -div(x, y) { +div(x Int, y Int) -> Int { return x / y } -div10(x) { +div10(x Int) -> Int { return x / 10 } \ No newline at end of file diff --git a/tests/programs/negation.q b/tests/programs/negation.q index 709f995..089d4d7 100644 --- a/tests/programs/negation.q +++ b/tests/programs/negation.q @@ -5,6 +5,6 @@ main() { assert neg(256) == -256 } -neg(x) { +neg(x Int) -> Int { return -x } \ No newline at end of file diff --git a/tests/programs/nested-calls.q b/tests/programs/nested-calls.q index a23e15c..e555b99 100644 --- a/tests/programs/nested-calls.q +++ b/tests/programs/nested-calls.q @@ -2,6 +2,6 @@ main() { assert f(f(f(1))) == 4 } -f(x) { +f(x Int) -> Int { return x + 1 } \ No newline at end of file diff --git a/tests/programs/op-assign.q b/tests/programs/op-assign.q index 496b3a5..257b6ac 100644 --- a/tests/programs/op-assign.q +++ b/tests/programs/op-assign.q @@ -2,7 +2,7 @@ main() { f(10) } -f(new) { +f(new Int) { old := new new -= 1 assert new != old diff --git a/tests/programs/param-multi.q b/tests/programs/param-multi.q index 1267e94..0e19661 100644 --- a/tests/programs/param-multi.q +++ b/tests/programs/param-multi.q @@ -2,11 +2,11 @@ main() { assert f(1, 2, 3) == 21 } -f(x, y, z) { +f(x Int, y Int, z Int) -> Int { w := g(4, 5, 6) return x + y + z + w } -g(x, y, z) { +g(x Int, y Int, z Int) -> Int { return x + y + z } \ No newline at end of file diff --git a/tests/programs/param-order.q b/tests/programs/param-order.q index a36d6e8..2b8ef0f 100644 --- a/tests/programs/param-order.q +++ b/tests/programs/param-order.q @@ -2,11 +2,11 @@ main() { f(1, 2, 3, 4, 5, 6) } -f(a, b, c, d, e, f) { - return g(f, e, d, c, b, a) +f(a Int, b Int, c Int, d Int, e Int, f Int) { + g(f, e, d, c, b, a) } -g(a, b, c, d, e, f) { +g(a Int, b Int, c Int, d Int, e Int, f Int) { assert a == 6 assert b == 5 assert c == 4 diff --git a/tests/programs/param.q b/tests/programs/param.q index 11ee501..5e1628d 100644 --- a/tests/programs/param.q +++ b/tests/programs/param.q @@ -2,11 +2,11 @@ main() { assert f(1) == 3 } -f(x) { +f(x Int) -> Int { y := g() return x + y } -g() { +g() -> Int { return 2 } \ No newline at end of file diff --git a/tests/programs/return-multi.q b/tests/programs/return-multi.q index 47e72be..be81c42 100644 --- a/tests/programs/return-multi.q +++ b/tests/programs/return-multi.q @@ -15,14 +15,14 @@ main() { assert i == 1 + 4 } -reverse2(a, b) { +reverse2(a Int, b Int) -> (Int, Int) { return b, a } -reverse3(a, b, c) { +reverse3(a Int, b Int, c Int) -> (Int, Int, Int) { return c, b, a } -mix4(a, b, c, d) { +mix4(a Int, b Int, c Int, d Int) -> (Int, Int, Int, Int) { return d + a, c + b, b + c, a + d } \ No newline at end of file diff --git a/tests/programs/return.q b/tests/programs/return.q index f5e13d5..36095bc 100644 --- a/tests/programs/return.q +++ b/tests/programs/return.q @@ -2,10 +2,10 @@ main() { assert f(2) == 6 } -f(x) { +f(x Int) -> Int { return x + 1 + g(x) } -g(x) { +g(x Int) -> Int { return x + 1 } \ No newline at end of file diff --git a/tests/programs/reuse.q b/tests/programs/reuse.q index 010f747..4658edb 100644 --- a/tests/programs/reuse.q +++ b/tests/programs/reuse.q @@ -2,6 +2,6 @@ main() { assert f(1) == 3 } -f(x) { +f(x Int) -> Int { return x + 1 + x } \ No newline at end of file diff --git a/tests/programs/square-sum.q b/tests/programs/square-sum.q index 04b1237..a9c0850 100644 --- a/tests/programs/square-sum.q +++ b/tests/programs/square-sum.q @@ -2,6 +2,6 @@ main() { assert f(2, 3) == 25 } -f(x, y) { +f(x Int, y Int) -> Int { return (x + y) * (x + y) } \ No newline at end of file diff --git a/tests/programs_test.go b/tests/programs_test.go index 39c5677..7e002a7 100644 --- a/tests/programs_test.go +++ b/tests/programs_test.go @@ -40,7 +40,7 @@ var programs = []struct { {"modulo", "", "", 0}, {"modulo-assign", "", "", 0}, {"div-split", "", "", 0}, - {"64-bit", "", "", 0}, + {"int64", "", "", 0}, {"negative", "", "", 0}, {"negation", "", "", 0}, {"square-sum", "", "", 0},