checker: remove hack and enforce type checking
parent
fa5fcee584
commit
a8c92e6dff
|
@ -151,9 +151,10 @@ TODO
|
||||||
*/
|
*/
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn v_calloc(n int) byteptr {
|
pub fn v_calloc(n int) byteptr {
|
||||||
return C.calloc(n, 1)
|
return C.calloc(n, 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn vcalloc(n int) byteptr {
|
pub fn vcalloc(n int) byteptr {
|
||||||
if n <= 0 {
|
if n <= 0 {
|
||||||
|
|
|
@ -1,12 +1,15 @@
|
||||||
module builtin
|
module builtin
|
||||||
|
|
||||||
// <string.h>
|
// <string.h>
|
||||||
fn C.memcpy(byteptr, byteptr, int) voidptr
|
fn C.memcpy(byteptr, byteptr, int) voidptr
|
||||||
|
|
||||||
|
|
||||||
fn C.memmove(byteptr, byteptr, int) voidptr
|
fn C.memmove(byteptr, byteptr, int) voidptr
|
||||||
fn C.calloc(int) byteptr
|
fn C.calloc(int) byteptr
|
||||||
// fn C.malloc(int) byteptr
|
fn C.malloc(int) byteptr
|
||||||
fn C.realloc(a byteptr, b int) byteptr
|
fn C.realloc(a byteptr, b int) byteptr
|
||||||
|
fn C.free(ptr voidptr)
|
||||||
|
fn C.exit(code int)
|
||||||
|
|
||||||
|
|
||||||
fn C.qsort(voidptr, int, int, voidptr)
|
fn C.qsort(voidptr, int, int, voidptr)
|
||||||
|
|
|
@ -149,6 +149,7 @@ pub fn (c mut Checker) struct_init(struct_init mut ast.StructInit) table.Type {
|
||||||
|
|
||||||
pub fn (c mut Checker) infix_expr(infix_expr mut ast.InfixExpr) table.Type {
|
pub fn (c mut Checker) infix_expr(infix_expr mut ast.InfixExpr) table.Type {
|
||||||
// println('checker: infix expr(op $infix_expr.op.str())')
|
// println('checker: infix expr(op $infix_expr.op.str())')
|
||||||
|
c.expected_type = table.void_type
|
||||||
left_type := c.expr(infix_expr.left)
|
left_type := c.expr(infix_expr.left)
|
||||||
infix_expr.left_type = left_type
|
infix_expr.left_type = left_type
|
||||||
c.expected_type = left_type
|
c.expected_type = left_type
|
||||||
|
@ -156,29 +157,35 @@ pub fn (c mut Checker) infix_expr(infix_expr mut ast.InfixExpr) table.Type {
|
||||||
infix_expr.right_type = right_type
|
infix_expr.right_type = right_type
|
||||||
right := c.table.get_type_symbol(right_type)
|
right := c.table.get_type_symbol(right_type)
|
||||||
left := c.table.get_type_symbol(left_type)
|
left := c.table.get_type_symbol(left_type)
|
||||||
if infix_expr.op == .key_in && !(right.kind in [.array, .map, .string]) {
|
|
||||||
c.error('`in` can only be used with an array/map/string.', infix_expr.pos)
|
|
||||||
}
|
|
||||||
if infix_expr.op == .left_shift {
|
if infix_expr.op == .left_shift {
|
||||||
if left.kind != .array && !left.is_int() {
|
if left.kind != .array && !left.is_int() {
|
||||||
//c.error('<< can only be used with numbers and arrays', infix_expr.pos)
|
//c.error('<< can only be used with numbers and arrays', infix_expr.pos)
|
||||||
c.error('incompatible types: $left.name << $right.name', infix_expr.pos)
|
c.error('incompatible types: $left.name << $right.name', infix_expr.pos)
|
||||||
|
return table.void_type
|
||||||
}
|
}
|
||||||
if left.kind == .array && infix_expr.op == .left_shift {
|
if left.kind == .array {
|
||||||
// `array << elm`
|
// `array << elm`
|
||||||
// the expressions have different types (array_x and x)
|
// the expressions have different types (array_x and x)
|
||||||
if right.kind != .array && !c.table.check(c.table.value_type(left_type), right_type) {
|
if c.table.check(c.table.value_type(left_type), right_type) {
|
||||||
c.error('incompatible types: $left.name << $right.name', infix_expr.pos)
|
// []T << T
|
||||||
|
return table.void_type
|
||||||
}
|
}
|
||||||
|
if right.kind == .array && c.table.check(c.table.value_type(left_type), c.table.value_type(right_type)) {
|
||||||
|
// []T << []T
|
||||||
|
return table.void_type
|
||||||
|
}
|
||||||
|
c.error('incompatible types: $left.name << $right.name', infix_expr.pos)
|
||||||
return table.void_type
|
return table.void_type
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !c.table.check(right_type, left_type) {
|
if infix_expr.op == .key_in {
|
||||||
// `elm in array`
|
if !(right.kind in [.array, .map, .string]) {
|
||||||
if right.kind in [.array, .map] && infix_expr.op == .key_in {
|
c.error('`in` can only be used with an array/map/string.', infix_expr.pos)
|
||||||
return table.bool_type
|
|
||||||
}
|
}
|
||||||
// fot type-unresolved consts
|
return table.bool_type
|
||||||
|
}
|
||||||
|
if !c.table.check(right_type, left_type) {
|
||||||
|
// for type-unresolved consts
|
||||||
if left_type == table.void_type || right_type == table.void_type {
|
if left_type == table.void_type || right_type == table.void_type {
|
||||||
return table.void_type
|
return table.void_type
|
||||||
}
|
}
|
||||||
|
@ -191,6 +198,7 @@ pub fn (c mut Checker) infix_expr(infix_expr mut ast.InfixExpr) table.Type {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (c mut Checker) assign_expr(assign_expr mut ast.AssignExpr) {
|
fn (c mut Checker) assign_expr(assign_expr mut ast.AssignExpr) {
|
||||||
|
c.expected_type = table.void_type
|
||||||
left_type := c.expr(assign_expr.left)
|
left_type := c.expr(assign_expr.left)
|
||||||
c.expected_type = left_type
|
c.expected_type = left_type
|
||||||
assign_expr.left_type = left_type
|
assign_expr.left_type = left_type
|
||||||
|
@ -291,17 +299,6 @@ pub fn (c mut Checker) call_expr(call_expr mut ast.CallExpr) table.Type {
|
||||||
if fn_name == 'typeof' {
|
if fn_name == 'typeof' {
|
||||||
return table.string_type
|
return table.string_type
|
||||||
}
|
}
|
||||||
// start hack: until v1 is fixed and c definitions are added for these
|
|
||||||
if fn_name in ['C.calloc', 'C.malloc', 'C.exit', 'C.free'] {
|
|
||||||
for arg in call_expr.args {
|
|
||||||
c.expr(arg.expr)
|
|
||||||
}
|
|
||||||
if fn_name in ['C.calloc', 'C.malloc'] {
|
|
||||||
return table.byteptr_type
|
|
||||||
}
|
|
||||||
return table.void_type
|
|
||||||
}
|
|
||||||
// end hack
|
|
||||||
// look for function in format `mod.fn` or `fn` (main/builtin)
|
// look for function in format `mod.fn` or `fn` (main/builtin)
|
||||||
mut f := table.Fn{}
|
mut f := table.Fn{}
|
||||||
mut found := false
|
mut found := false
|
||||||
|
|
Loading…
Reference in New Issue