From 80da2341aa85b9c62b1b423fa0734c9d7fe91ef3 Mon Sep 17 00:00:00 2001 From: joe-conigliaro Date: Tue, 31 Dec 2019 20:53:30 +1100 Subject: [PATCH] v: fix unary `+`,`-` & rename token.TokenKind to token.Kind --- vlib/v/ast/ast.v | 16 +-- vlib/v/gen/cgen.v | 10 +- vlib/v/gen/tests/1.c | 2 + vlib/v/gen/tests/1.vv | 2 + vlib/v/parser/parser.v | 24 ++-- vlib/v/scanner/scanner.v | 4 +- vlib/v/scanner/scanner_test.v | 2 +- vlib/v/token/token.v | 228 +++++++++++++++++----------------- 8 files changed, 153 insertions(+), 135 deletions(-) diff --git a/vlib/v/ast/ast.v b/vlib/v/ast/ast.v index e27a4aefda..d73d8ed6b4 100644 --- a/vlib/v/ast/ast.v +++ b/vlib/v/ast/ast.v @@ -132,15 +132,15 @@ pub: pub struct Ident { pub: name string - tok_kind token.TokenKind + tok_kind token.Kind value string } pub struct BinaryExpr { pub: -// tok_kind token.TokenKind +// tok_kind token.Kind // op BinaryOp - op token.TokenKind + op token.Kind left Expr // left_type Type right Expr @@ -149,15 +149,15 @@ pub: pub struct UnaryExpr { pub: -// tok_kind token.TokenKind +// tok_kind token.Kind // op BinaryOp - op token.TokenKind + op token.Kind left Expr } pub struct IfExpr { pub: - tok_kind token.TokenKind + tok_kind token.Kind cond Expr stmts []Stmt else_ []Stmt @@ -170,7 +170,7 @@ pub: } pub struct ReturnStmt { - tok_kind token.TokenKind // or pos + tok_kind token.Kind // or pos results []Expr } @@ -178,7 +178,7 @@ pub struct AssignStmt { pub: left Expr right Expr - op token.TokenKind + op token.Kind } pub struct ArrayInit { diff --git a/vlib/v/gen/cgen.v b/vlib/v/gen/cgen.v index 6a9fc3e409..0c904eab6e 100644 --- a/vlib/v/gen/cgen.v +++ b/vlib/v/gen/cgen.v @@ -112,8 +112,14 @@ fn (g mut Gen) expr(node ast.Expr) { g.write(it.val) } ast.UnaryExpr { - g.expr(it.left) - g.write(it.op.str()) + // probably not :D + if it.op in [.inc, .dec] { + g.expr(it.left) + g.write(it.op.str()) + } else { + g.write(it.op.str()) + g.expr(it.left) + } } ast.StringLiteral { g.write('tos3("$it.val")') diff --git a/vlib/v/gen/tests/1.c b/vlib/v/gen/tests/1.c index f2f9a0d061..fb1b0206c4 100644 --- a/vlib/v/gen/tests/1.c +++ b/vlib/v/gen/tests/1.c @@ -1,5 +1,7 @@ int main() { int a = 10; a++; +int c = -a; +a == 1; return 0; } diff --git a/vlib/v/gen/tests/1.vv b/vlib/v/gen/tests/1.vv index 29ae4d536b..af5e50cc96 100644 --- a/vlib/v/gen/tests/1.vv +++ b/vlib/v/gen/tests/1.vv @@ -1,4 +1,6 @@ fn main() { a := 10 a++ + c := -a + a == 1 } diff --git a/vlib/v/parser/parser.v b/vlib/v/parser/parser.v index 0a7bce0716..65eb8b44a8 100644 --- a/vlib/v/parser/parser.v +++ b/vlib/v/parser/parser.v @@ -138,7 +138,7 @@ fn (p mut Parser) next() { // println(p.tok.str()) } -fn (p mut Parser) check(expected token.TokenKind) { +fn (p mut Parser) check(expected token.Kind) { if p.tok.kind != expected { s := 'syntax error: unexpected `${p.tok.kind.str()}`, expecting `${expected.str()}`' p.error(s) @@ -290,7 +290,8 @@ pub fn (p mut Parser) expr(rbp int) (ast.Expr,types.Type) { field_name := p.check_name() field_names << field_name p.check(.colon) - expr,field_type := p.expr(0) + // expr,field_type := p.expr(0) + expr,_ := p.expr(0) exprs << expr } node = ast.StructInit{ @@ -329,15 +330,21 @@ pub fn (p mut Parser) expr(rbp int) (ast.Expr,types.Type) { node,typ = p.if_expr() } .lpar { - node,typ = p.expr(0) + p.check(.lpar) + p.next() + node,typ = p.expr(token.lowest_prec) p.check(.rpar) } else { if p.tok.is_unary() { - expr,_ := p.expr(token.highest_prec) - node = ast.UnaryExpr{ - left: expr - } + pt := p.tok + p.next() + expr,t2 := p.expr(token.lowest_prec) + node = ast.UnaryExpr{ + left: expr + op: pt.kind + } + typ = t2 } else { verror('!unknown token ' + p.tok.str()) @@ -373,8 +380,7 @@ pub fn (p mut Parser) expr(rbp int) (ast.Expr,types.Type) { } } else { mut expr := ast.Expr{} - expr,t2 = p.expr(prev_tok.precedence()) - op := prev_tok.kind + expr,t2 = p.expr(prev_tok.precedence() - 1) if prev_tok.is_relational() { typ = types.bool_type } diff --git a/vlib/v/scanner/scanner.v b/vlib/v/scanner/scanner.v index c4f71c7b7a..c42abde0d8 100644 --- a/vlib/v/scanner/scanner.v +++ b/vlib/v/scanner/scanner.v @@ -75,9 +75,9 @@ pub fn new_scanner(text string) &Scanner { } } -fn (s &Scanner) scan_res(tok token.TokenKind, lit string) token.Token { +fn (s &Scanner) scan_res(tok_kind token.Kind, lit string) token.Token { return token.Token{ - tok,lit,s.line_nr + 1} + tok_kind,lit,s.line_nr + 1} } fn (s mut Scanner) ident_name() string { diff --git a/vlib/v/scanner/scanner_test.v b/vlib/v/scanner/scanner_test.v index b2b2f0b21b..9375b7c428 100644 --- a/vlib/v/scanner/scanner_test.v +++ b/vlib/v/scanner/scanner_test.v @@ -10,7 +10,7 @@ import ( fn test_scan() { text := 'println(2 + 3)' mut scanner := new_scanner(text) - mut token_kinds := []token.TokenKind + mut token_kinds := []token.Kind for { tok := scanner.scan() if tok.kind == .eof { diff --git a/vlib/v/token/token.v b/vlib/v/token/token.v index db39a2dea1..783e2cad94 100644 --- a/vlib/v/token/token.v +++ b/vlib/v/token/token.v @@ -5,14 +5,14 @@ module token pub struct Token { pub: - kind TokenKind // the token number/enum; for quick comparisons + kind Kind // the token number/enum; for quick comparisons lit string // literal representation of the token line_nr int // the line number in the source where the token occured // name_idx int // name table index for O(1) lookup // pos int // the position of the token in scanner text } -pub enum TokenKind { +pub enum Kind { eof name // user number // 123 @@ -124,7 +124,7 @@ pub enum TokenKind { } const ( - assign_tokens = [TokenKind.assign, .plus_assign, .minus_assign, .mult_assign, + assign_tokens = [Kind.assign, .plus_assign, .minus_assign, .mult_assign, .div_assign, .xor_assign, .mod_assign, .or_assign, .and_assign, .righ_shift_assign, .left_shift_assign] nr_tokens = 141 @@ -133,119 +133,119 @@ const ( // Keywords['return'] == .key_return fn build_keys() map[string]int { mut res := map[string]int - for t := int(TokenKind.keyword_beg) + 1; t < int(TokenKind.keyword_end); t++ { + for t := int(Kind.keyword_beg) + 1; t < int(Kind.keyword_end); t++ { key := token_str[t] res[key] = t } return res } -// TODO remove once we have `enum TokenKind { name('name') if('if') ... }` +// TODO remove once we have `enum Kind { name('name') if('if') ... }` fn build_token_str() []string { mut s := [''].repeat(nr_tokens) - s[TokenKind.keyword_beg] = '' - s[TokenKind.keyword_end] = '' - s[TokenKind.eof] = 'eof' - s[TokenKind.name] = 'name' - s[TokenKind.number] = 'number' - s[TokenKind.str] = 'STR' - s[TokenKind.chartoken] = 'char' - s[TokenKind.plus] = '+' - s[TokenKind.minus] = '-' - s[TokenKind.mul] = '*' - s[TokenKind.div] = '/' - s[TokenKind.mod] = '%' - s[TokenKind.xor] = '^' - s[TokenKind.bit_not] = '~' - s[TokenKind.pipe] = '|' - s[TokenKind.hash] = '#' - s[TokenKind.amp] = '&' - s[TokenKind.inc] = '++' - s[TokenKind.dec] = '--' - s[TokenKind.and] = '&&' - s[TokenKind.logical_or] = '||' - s[TokenKind.not] = '!' - s[TokenKind.dot] = '.' - s[TokenKind.dotdot] = '..' - s[TokenKind.ellipsis] = '...' - s[TokenKind.comma] = ',' - // s[TokenKind.at] = '@' - s[TokenKind.semicolon] = ';' - s[TokenKind.colon] = ':' - s[TokenKind.arrow] = '=>' - s[TokenKind.assign] = '=' - s[TokenKind.decl_assign] = ':=' - s[TokenKind.plus_assign] = '+=' - s[TokenKind.minus_assign] = '-=' - s[TokenKind.mult_assign] = '*=' - s[TokenKind.div_assign] = '/=' - s[TokenKind.xor_assign] = '^=' - s[TokenKind.mod_assign] = '%=' - s[TokenKind.or_assign] = '|=' - s[TokenKind.and_assign] = '&=' - s[TokenKind.righ_shift_assign] = '>>=' - s[TokenKind.left_shift_assign] = '<<=' - s[TokenKind.lcbr] = '{' - s[TokenKind.rcbr] = '}' - s[TokenKind.lpar] = '(' - s[TokenKind.rpar] = ')' - s[TokenKind.lsbr] = '[' - s[TokenKind.rsbr] = ']' - s[TokenKind.eq] = '==' - s[TokenKind.ne] = '!=' - s[TokenKind.gt] = '>' - s[TokenKind.lt] = '<' - s[TokenKind.ge] = '>=' - s[TokenKind.le] = '<=' - s[TokenKind.question] = '?' - s[TokenKind.left_shift] = '<<' - s[TokenKind.righ_shift] = '>>' - s[TokenKind.line_comment] = '// line comment' - s[TokenKind.mline_comment] = '/* mline comment */' - s[TokenKind.nl] = 'NLL' - s[TokenKind.dollar] = '$' - s[TokenKind.str_dollar] = '$2' - s[TokenKind.key_assert] = 'assert' - s[TokenKind.key_struct] = 'struct' - s[TokenKind.key_if] = 'if' - // s[TokenKind.key_it] = 'it' - s[TokenKind.key_else] = 'else' - s[TokenKind.key_asm] = 'asm' - s[TokenKind.key_return] = 'return' - s[TokenKind.key_module] = 'module' - s[TokenKind.key_sizeof] = 'sizeof' - s[TokenKind.key_go] = 'go' - s[TokenKind.key_goto] = 'goto' - s[TokenKind.key_const] = 'const' - s[TokenKind.key_mut] = 'mut' - s[TokenKind.key_type] = 'type' - s[TokenKind.key_for] = 'for' - s[TokenKind.key_switch] = 'switch' - s[TokenKind.key_fn] = 'fn' - s[TokenKind.key_true] = 'true' - s[TokenKind.key_false] = 'false' - s[TokenKind.key_continue] = 'continue' - s[TokenKind.key_break] = 'break' - s[TokenKind.key_import] = 'import' - s[TokenKind.key_embed] = 'embed' - s[TokenKind.key_unsafe] = 'unsafe' - // TokenKinds[key_typeof] = 'typeof' - s[TokenKind.key_enum] = 'enum' - s[TokenKind.key_interface] = 'interface' - s[TokenKind.key_pub] = 'pub' - s[TokenKind.key_import_const] = 'import_const' - s[TokenKind.key_in] = 'in' - s[TokenKind.key_atomic] = 'atomic' - s[TokenKind.key_orelse] = 'or' - s[TokenKind.key_global] = '__global' - s[TokenKind.key_union] = 'union' - s[TokenKind.key_static] = 'static' - s[TokenKind.key_as] = 'as' - s[TokenKind.key_defer] = 'defer' - s[TokenKind.key_match] = 'match' - s[TokenKind.key_select] = 'select' - s[TokenKind.key_none] = 'none' - s[TokenKind.key_offsetof] = '__offsetof' + s[Kind.keyword_beg] = '' + s[Kind.keyword_end] = '' + s[Kind.eof] = 'eof' + s[Kind.name] = 'name' + s[Kind.number] = 'number' + s[Kind.str] = 'STR' + s[Kind.chartoken] = 'char' + s[Kind.plus] = '+' + s[Kind.minus] = '-' + s[Kind.mul] = '*' + s[Kind.div] = '/' + s[Kind.mod] = '%' + s[Kind.xor] = '^' + s[Kind.bit_not] = '~' + s[Kind.pipe] = '|' + s[Kind.hash] = '#' + s[Kind.amp] = '&' + s[Kind.inc] = '++' + s[Kind.dec] = '--' + s[Kind.and] = '&&' + s[Kind.logical_or] = '||' + s[Kind.not] = '!' + s[Kind.dot] = '.' + s[Kind.dotdot] = '..' + s[Kind.ellipsis] = '...' + s[Kind.comma] = ',' + // s[Kind.at] = '@' + s[Kind.semicolon] = ';' + s[Kind.colon] = ':' + s[Kind.arrow] = '=>' + s[Kind.assign] = '=' + s[Kind.decl_assign] = ':=' + s[Kind.plus_assign] = '+=' + s[Kind.minus_assign] = '-=' + s[Kind.mult_assign] = '*=' + s[Kind.div_assign] = '/=' + s[Kind.xor_assign] = '^=' + s[Kind.mod_assign] = '%=' + s[Kind.or_assign] = '|=' + s[Kind.and_assign] = '&=' + s[Kind.righ_shift_assign] = '>>=' + s[Kind.left_shift_assign] = '<<=' + s[Kind.lcbr] = '{' + s[Kind.rcbr] = '}' + s[Kind.lpar] = '(' + s[Kind.rpar] = ')' + s[Kind.lsbr] = '[' + s[Kind.rsbr] = ']' + s[Kind.eq] = '==' + s[Kind.ne] = '!=' + s[Kind.gt] = '>' + s[Kind.lt] = '<' + s[Kind.ge] = '>=' + s[Kind.le] = '<=' + s[Kind.question] = '?' + s[Kind.left_shift] = '<<' + s[Kind.righ_shift] = '>>' + s[Kind.line_comment] = '// line comment' + s[Kind.mline_comment] = '/* mline comment */' + s[Kind.nl] = 'NLL' + s[Kind.dollar] = '$' + s[Kind.str_dollar] = '$2' + s[Kind.key_assert] = 'assert' + s[Kind.key_struct] = 'struct' + s[Kind.key_if] = 'if' + // s[Kind.key_it] = 'it' + s[Kind.key_else] = 'else' + s[Kind.key_asm] = 'asm' + s[Kind.key_return] = 'return' + s[Kind.key_module] = 'module' + s[Kind.key_sizeof] = 'sizeof' + s[Kind.key_go] = 'go' + s[Kind.key_goto] = 'goto' + s[Kind.key_const] = 'const' + s[Kind.key_mut] = 'mut' + s[Kind.key_type] = 'type' + s[Kind.key_for] = 'for' + s[Kind.key_switch] = 'switch' + s[Kind.key_fn] = 'fn' + s[Kind.key_true] = 'true' + s[Kind.key_false] = 'false' + s[Kind.key_continue] = 'continue' + s[Kind.key_break] = 'break' + s[Kind.key_import] = 'import' + s[Kind.key_embed] = 'embed' + s[Kind.key_unsafe] = 'unsafe' + // Kinds[key_typeof] = 'typeof' + s[Kind.key_enum] = 'enum' + s[Kind.key_interface] = 'interface' + s[Kind.key_pub] = 'pub' + s[Kind.key_import_const] = 'import_const' + s[Kind.key_in] = 'in' + s[Kind.key_atomic] = 'atomic' + s[Kind.key_orelse] = 'or' + s[Kind.key_global] = '__global' + s[Kind.key_union] = 'union' + s[Kind.key_static] = 'static' + s[Kind.key_as] = 'as' + s[Kind.key_defer] = 'defer' + s[Kind.key_match] = 'match' + s[Kind.key_select] = 'select' + s[Kind.key_none] = 'none' + s[Kind.key_offsetof] = '__offsetof' return s } @@ -254,8 +254,8 @@ const ( keywords = build_keys() ) -pub fn key_to_token(key string) TokenKind { - a := TokenKind(keywords[key]) +pub fn key_to_token(key string) Kind { + a := Kind(keywords[key]) return a } @@ -263,7 +263,7 @@ pub fn is_key(key string) bool { return int(key_to_token(key)) > 0 } -pub fn is_decl(t TokenKind) bool { +pub fn is_decl(t Kind) bool { return t in [.key_enum, .key_interface, .key_fn, .key_struct, .key_type, .key_const, .key_import_const, .key_pub, .eof] } @@ -271,7 +271,7 @@ pub fn (t Token) is_assign() bool { return t.kind in assign_tokens } -fn (t []TokenKind) contains(val TokenKind) bool { +fn (t []Kind) contains(val Kind) bool { for tt in t { if tt == val { return true @@ -280,7 +280,7 @@ fn (t []TokenKind) contains(val TokenKind) bool { return false } -pub fn (t TokenKind) str() string { +pub fn (t Kind) str() string { if t == .number { return 'number' } @@ -368,6 +368,8 @@ pub fn (tok Token) is_left_assoc() bool { .mul, .div, .mod, // `^` | `||` | `&` .xor, .logical_or, .and, + // `==` | `!=` + .eq, .ne, // `<` | `<=` | `>` | `>=` .lt, .le, .gt, .ge, // `,`