checker/parser: allow for fixed array with sizes defined with a const

pull/4340/head
Delyan Angelov 2020-04-10 22:00:54 +03:00
parent 514d989a27
commit 217e6f3b8e
9 changed files with 99 additions and 26 deletions

View File

@ -302,7 +302,6 @@ pub fn (s Socket) close() ?int {
pub const (
CRLF = '\r\n'
MAX_READ = 400
xxx = 400
MSG_PEEK = 0x02
)
// write - write a string with CRLF after it over the socket s
@ -317,7 +316,6 @@ pub fn (s Socket) write(str string) ?int {
// read_line - retrieves a line from the socket s (i.e. a string ended with \n)
pub fn (s Socket) read_line() string {
//mut buf2 := [xxx]byte // where C.recv will store the network data
mut buf := [MAX_READ]byte // where C.recv will store the network data
mut res := '' // The final result, including the ending \n.
for {
@ -385,4 +383,3 @@ pub fn (s Socket) get_port() int {
C.getsockname(s.sockfd, &addr, &size)
return C.ntohs(addr.sin_port)
}

View File

@ -588,6 +588,8 @@ pub struct ArrayInit {
pub:
pos token.Position
exprs []Expr
is_fixed bool
mod string
mut:
elem_type table.Type
typ table.Type

View File

@ -56,7 +56,8 @@ pub fn (s &Scope) is_known(name string) bool {
pub fn (s &Scope) find_var(name string) ?Var {
if obj := s.find(name) {
match obj {
v := ScopeObject(obj)
match v {
Var {
return *it
}
@ -68,7 +69,8 @@ pub fn (s &Scope) find_var(name string) ?Var {
pub fn (s &Scope) find_const(name string) ?ConstField {
if obj := s.find(name) {
match obj {
cf := ScopeObject(obj)
match cf {
ConstField {
return *it
}

View File

@ -85,6 +85,9 @@ pub fn (x Expr) str() string {
PrefixExpr {
return it.op.str() + it.right.str()
}
CharLiteral {
return '`$it.val`'
}
IntegerLiteral {
return it.val
}

View File

@ -706,7 +706,7 @@ pub fn (c mut Checker) array_init(array_init mut ast.ArrayInit) table.Type {
idx := c.table.find_or_register_array(elem_type, 1)
array_init.typ = table.new_type(idx)
array_init.elem_type = elem_type
} else if array_init.exprs.len == 1 && array_init.elem_type != table.void_type {
} else if array_init.is_fixed && array_init.exprs.len == 1 && array_init.elem_type != table.void_type {
// [50]byte
mut fixed_size := 1
match array_init.exprs[0] {
@ -714,19 +714,23 @@ pub fn (c mut Checker) array_init(array_init mut ast.ArrayInit) table.Type {
fixed_size = it.val.int()
}
ast.Ident {
/*
QTODO
scope := c.file.scope.innermost(array_init.pos.pos)
if obj := c.file.global_scope.find(it.name) {
//if obj := c.file.global_scope.find_const(it.name) {
//if obj := scope.find(it.name) {
//scope := c.file.scope.innermost(array_init.pos.pos)
//eprintln('scope: ${scope.str()}')
//scope.find(it.name) or {
// c.error('undefined: `$it.name`', array_init.pos)
//}
mut full_const_name := if it.mod == 'main' { it.name } else {it.mod + '.' + it.name }
if obj := c.file.global_scope.find_const( full_const_name ) {
cf := ast.ConstField(obj)
if cint := is_const_integer(cf) {
fixed_size = cint.val.int()
}
} else {
c.error(it.name, array_init.pos)
c.error('non existant integer const $full_const_name while initializing the size of a static array', array_init.pos)
}
scope.find(it.name) or {
c.error('undefined: `$it.name`', array_init.pos)
}
*/
}
else {
} else {
c.error('expecting `int` for fixed size', array_init.pos)
}
}
@ -737,6 +741,16 @@ pub fn (c mut Checker) array_init(array_init mut ast.ArrayInit) table.Type {
return array_init.typ
}
fn is_const_integer(cfield ast.ConstField) ?ast.IntegerLiteral {
match cfield.expr {
ast.IntegerLiteral {
return *it
}
else {}
}
return none
}
fn (c mut Checker) stmt(node ast.Stmt) {
// c.expected_type = table.void_type
match mut node {

View File

@ -723,7 +723,7 @@ fn (g mut Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) {
mut is_fixed_array_init := false
match val {
ast.ArrayInit {
is_fixed_array_init = right_sym.kind == .array_fixed
is_fixed_array_init = it.is_fixed
}
else {}
}
@ -740,15 +740,15 @@ fn (g mut Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) {
return
}
}
if !is_fixed_array_init {
if is_fixed_array_init {
g.write('= {0}')
} else {
g.write(' = ')
if !is_decl {
g.expr_with_cast(val, assign_stmt.left_types[i], ident_var_info.typ)
} else {
g.expr(val)
}
} else if is_fixed_array_init {
g.write('= {0}')
}
if gen_or {
g.or_block(ident.name, or_stmts, return_type)

View File

@ -513,19 +513,28 @@ fn (p mut Parser) range_expr(low ast.Expr) ast.Expr {
return node
}
*/
pub fn (p &Parser) error(s string) {
p.error_with_pos(s, p.tok.position())
}
pub fn (p &Parser) warn(s string) {
p.warn_with_pos(s, p.tok.position())
}
pub fn (p &Parser) error_with_pos(s string, pos token.Position) {
mut kind := 'error:'
if p.pref.is_verbose {
print_backtrace()
kind = 'parser error:'
}
ferror := util.formatted_error(kind, s, p.file_name, p.tok.position())
ferror := util.formatted_error(kind, s, p.file_name, pos)
eprintln(ferror)
exit(1)
}
pub fn (p &Parser) warn(s string) {
ferror := util.formatted_error('warning:', s, p.file_name, p.tok.position())
pub fn (p &Parser) warn_with_pos(s string, pos token.Position) {
ferror := util.formatted_error('warning:', s, p.file_name, pos)
eprintln(ferror)
}
@ -1298,6 +1307,7 @@ fn (p mut Parser) array_init() ast.ArrayInit {
mut array_type := table.void_type
mut elem_type := table.void_type
mut exprs := []ast.Expr
is_fixed := false
if p.tok.kind == .rsbr {
// []typ => `[]` and `typ` must be on the same line
line_nr := p.tok.line_nr
@ -1311,7 +1321,7 @@ fn (p mut Parser) array_init() ast.ArrayInit {
array_type = table.new_type(idx)
}
} else {
// [1,2,3]
// [1,2,3] or [const]byte
for i := 0; p.tok.kind != .rsbr; i++ {
expr := p.expr(0)
exprs << expr
@ -1325,7 +1335,7 @@ fn (p mut Parser) array_init() ast.ArrayInit {
// [100]byte
if exprs.len == 1 && p.tok.kind in [.name, .amp] && p.tok.line_nr == line_nr {
elem_type = p.parse_type()
// p.warn('fixed size array')
is_fixed = true
}
}
// !
@ -1343,6 +1353,8 @@ fn (p mut Parser) array_init() ast.ArrayInit {
len: len
}
return ast.ArrayInit{
is_fixed: is_fixed
mod: p.mod
elem_type: elem_type
typ: array_type
exprs: exprs

View File

@ -0,0 +1,39 @@
const (
sbuffer_size = 10
)
fn test_hardcoded_static_arr(){
myints := [10]int
size := sizeof( myints )
assert size == 40
}
fn test_const_based_static_arr(){
myints := [sbuffer_size]int
size := sizeof( myints )
assert size == 40
}
fn test_const_based_static_arr_of_f64(){
myf64 := [sbuffer_size]f64
size := sizeof( myf64 )
assert size == 80
}
fn test_const_based_static_arr_of_f32(){
myf32 := [sbuffer_size]f32
size := sizeof( myf32 )
assert size == 40
}
fn test_const_based_static_arr_of_i8(){
myi8 := [sbuffer_size]i8
size := sizeof( myi8 )
assert size == 10
}
fn test_const_based_static_arr_of_i16(){
myi16 := [sbuffer_size]i16
size := sizeof( myi16 )
assert size == 20
}

View File

@ -10,6 +10,10 @@ pub:
len int // length of the literal in the source
}
pub fn (pos Position) str() string {
return 'Position{ line_nr: $pos.line_nr, pos: $pos.pos, len: $pos.len }'
}
[inline]
pub fn (tok &Token) position() Position {
return Position{