checker: remove hack and enforce type checking

pull/4274/head
lutherwenxu 2020-04-07 09:27:06 +08:00 committed by GitHub
parent fa5fcee584
commit a8c92e6dff
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 25 additions and 24 deletions

View File

@ -151,9 +151,10 @@ TODO
*/
}
pub fn v_calloc(n int) byteptr {
return C.calloc(n, 1)
}
}
pub fn vcalloc(n int) byteptr {
if n <= 0 {

View File

@ -1,12 +1,15 @@
module builtin
// <string.h>
fn C.memcpy(byteptr, byteptr, int) voidptr
fn C.memmove(byteptr, byteptr, int) voidptr
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.free(ptr voidptr)
fn C.exit(code int)
fn C.qsort(voidptr, int, int, voidptr)

View File

@ -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 {
// println('checker: infix expr(op $infix_expr.op.str())')
c.expected_type = table.void_type
left_type := c.expr(infix_expr.left)
infix_expr.left_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
right := c.table.get_type_symbol(right_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 left.kind != .array && !left.is_int() {
//c.error('<< can only be used with numbers and arrays', 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`
// the expressions have different types (array_x and x)
if right.kind != .array && !c.table.check(c.table.value_type(left_type), right_type) {
c.error('incompatible types: $left.name << $right.name', infix_expr.pos)
if c.table.check(c.table.value_type(left_type), right_type) {
// []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
}
}
if !c.table.check(right_type, left_type) {
// `elm in array`
if right.kind in [.array, .map] && infix_expr.op == .key_in {
return table.bool_type
if infix_expr.op == .key_in {
if !(right.kind in [.array, .map, .string]) {
c.error('`in` can only be used with an array/map/string.', infix_expr.pos)
}
// 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 {
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) {
c.expected_type = table.void_type
left_type := c.expr(assign_expr.left)
c.expected_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' {
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)
mut f := table.Fn{}
mut found := false