Skip to content

Commit

Permalink
parser, transformer: fix transformer.infix_expr() and cleanup parse_t…
Browse files Browse the repository at this point in the history
…ypes.v (related #19269) (#19276)
  • Loading branch information
yuyi98 authored Sep 7, 2023
1 parent a23f89e commit 055e113
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 67 deletions.
101 changes: 38 additions & 63 deletions vlib/v/parser/parse_type.v
Original file line number Diff line number Diff line change
Expand Up @@ -15,57 +15,58 @@ fn (mut p Parser) parse_array_type(expecting token.Kind, is_option bool) ast.Typ
// fixed array
if p.tok.kind in [.number, .name] {
mut fixed_size := 0
size_expr := p.expr(0)
mut size_expr := p.expr(0)
if p.pref.is_fmt {
fixed_size = 987654321
} else {
match size_expr {
match mut size_expr {
ast.IntegerLiteral {
fixed_size = size_expr.val.int()
}
ast.Ident {
mut show_non_const_error := false
fixed_size, show_non_const_error = p.check_and_eval_const_val(size_expr)
mut show_non_const_error := true
if mut const_field := p.table.global_scope.find_const('${p.mod}.${size_expr.name}') {
if mut const_field.expr is ast.IntegerLiteral {
fixed_size = const_field.expr.val.int()
show_non_const_error = false
} else {
if mut const_field.expr is ast.InfixExpr {
// QUESTION: this should most likely no be done in the parser, right?
mut t := transformer.new_transformer_with_table(p.table,
p.pref)
folded_expr := t.infix_expr(mut const_field.expr)

if folded_expr is ast.IntegerLiteral {
fixed_size = folded_expr.val.int()
show_non_const_error = false
}
}
}
} else {
if p.pref.is_fmt {
// for vfmt purposes, pretend the constant does exist
// it may have been defined in another .v file:
fixed_size = 1
show_non_const_error = false
}
}
if show_non_const_error {
p.error_with_pos('non-constant array bound `${size_expr.name}`',
size_expr.pos)
}
}
ast.InfixExpr {
mut show_non_const_error := false
mut left_val := 1
mut right_val := 1
if size_expr.left is ast.Ident {
left_val, show_non_const_error = p.check_and_eval_const_val(size_expr.left)
if show_non_const_error {
p.error_with_pos('non-constant array bound `${size_expr.left.name}`',
size_expr.left.pos)
}
}
if size_expr.right is ast.Ident && !show_non_const_error {
right_val, show_non_const_error = p.check_and_eval_const_val(size_expr.right)
if show_non_const_error {
p.error_with_pos('non-constant array bound `${size_expr.right.name}`',
size_expr.right.pos)
}
mut show_non_const_error := true
mut t := transformer.new_transformer_with_table(p.table, p.pref)
folded_expr := t.infix_expr(mut size_expr)

if folded_expr is ast.IntegerLiteral {
fixed_size = folded_expr.val.int()
show_non_const_error = false
}
match size_expr.op {
.plus {
fixed_size = left_val + right_val
}
.minus {
fixed_size = left_val - right_val
}
.mul {
fixed_size = left_val * right_val
}
.div {
fixed_size = left_val / right_val
}
else {
p.error_with_pos('fixed array size cannot use non-constant value',
size_expr.pos)
}
if show_non_const_error {
p.error_with_pos('fixed array size cannot use non-constant eval value',
size_expr.pos)
}
}
else {
Expand Down Expand Up @@ -851,29 +852,3 @@ fn (mut p Parser) parse_generic_inst_type(name string) ast.Type {
}
return p.find_type_or_add_placeholder(name, .v).set_flag(.generic)
}

// return value and show_non_const_error
fn (mut p Parser) check_and_eval_const_val(expr ast.Ident) (int, bool) {
if mut const_field := p.table.global_scope.find_const('${p.mod}.${expr.name}') {
if mut const_field.expr is ast.IntegerLiteral {
return const_field.expr.val.int(), false
} else {
if mut const_field.expr is ast.InfixExpr {
// QUESTION: this should most likely no be done in the parser, right?
mut t := transformer.new_transformer(p.pref)
folded_expr := t.infix_expr(mut const_field.expr)

if folded_expr is ast.IntegerLiteral {
return folded_expr.val.int(), false
}
}
}
} else {
if p.pref.is_fmt {
// for vfmt purposes, pretend the constant does exist
// it may have been defined in another .v file:
return 1, false
}
}
return 0, true
}
6 changes: 3 additions & 3 deletions vlib/v/tests/fixed_array_const_size_test.v
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@ fn test_int_const_used_as_fixed_array_size() {
}

const (
rows = 4
cols = 4
rows = 2
cols = 3
)

struct Matrix {
Expand All @@ -57,5 +57,5 @@ struct Matrix {
fn test_infix_const_expr_used_as_fixed_array_size() {
mat := Matrix{}
println(mat)
assert mat.data.len == 16
assert mat.data.len == 6
}
35 changes: 34 additions & 1 deletion vlib/v/transformer/transformer.v
Original file line number Diff line number Diff line change
Expand Up @@ -695,7 +695,8 @@ pub fn (mut t Transformer) expr(mut node ast.Expr) ast.Expr {
}
else {}
}
}*/
}
*/
else {}
}
return node
Expand All @@ -708,9 +709,41 @@ pub fn (mut t Transformer) call_expr(mut node ast.CallExpr) ast.Expr {
return node
}

fn (mut t Transformer) trans_const_value_to_literal(mut expr ast.Expr) {
mut expr_ := expr
if mut expr_ is ast.Ident {
if mut obj := t.table.global_scope.find_const(expr_.mod + '.' + expr_.name) {
if mut obj.expr is ast.BoolLiteral {
expr = obj.expr
} else if mut obj.expr is ast.IntegerLiteral {
expr = obj.expr
} else if mut obj.expr is ast.FloatLiteral {
expr = obj.expr
} else if mut obj.expr is ast.StringLiteral {
expr = obj.expr
} else if mut obj.expr is ast.InfixExpr {
folded_expr := t.infix_expr(mut obj.expr)
if folded_expr is ast.BoolLiteral {
expr = folded_expr
} else if folded_expr is ast.IntegerLiteral {
expr = folded_expr
} else if folded_expr is ast.FloatLiteral {
expr = folded_expr
} else if folded_expr is ast.StringLiteral {
expr = folded_expr
}
}
}
}
}

pub fn (mut t Transformer) infix_expr(mut node ast.InfixExpr) ast.Expr {
node.left = t.expr(mut node.left)
node.right = t.expr(mut node.right)
if !t.pref.translated {
t.trans_const_value_to_literal(mut node.left)
t.trans_const_value_to_literal(mut node.right)
}

mut pos := node.left.pos()
pos.extend(node.pos)
Expand Down

0 comments on commit 055e113

Please sign in to comment.