From 5e541e1f1163a77a10b408218000f8fc23c5f640 Mon Sep 17 00:00:00 2001 From: Delyan Angelov Date: Sat, 7 Mar 2020 18:37:55 +0200 Subject: [PATCH] vfmt: alias type and sum type + sum type fix --- vlib/compiler/aparser.v | 1 + vlib/compiler/expression.v | 4 +- vlib/v/ast/ast.v | 12 +++- vlib/v/fmt/fmt.v | 39 ++++++++++++- vlib/v/fmt/fmt_test.v | 2 +- .../import_multiple_with_alias_expected.vv | 5 ++ .../tests/import_multiple_with_alias_input.vv | 3 + vlib/v/fmt/tests/simple_expected.vv | 2 + vlib/v/fmt/tests/types_expected.vv | 9 +++ vlib/v/fmt/tests/types_input.vv | 10 ++++ vlib/v/parser/parser.v | 55 +++++++++++-------- vlib/v/table/atype_symbols.v | 15 ++++- 12 files changed, 125 insertions(+), 32 deletions(-) create mode 100644 vlib/v/fmt/tests/import_multiple_with_alias_expected.vv create mode 100644 vlib/v/fmt/tests/import_multiple_with_alias_input.vv create mode 100644 vlib/v/fmt/tests/types_expected.vv create mode 100644 vlib/v/fmt/tests/types_input.vv diff --git a/vlib/compiler/aparser.v b/vlib/compiler/aparser.v index b8377da0b2..b63ed5f5a6 100644 --- a/vlib/compiler/aparser.v +++ b/vlib/compiler/aparser.v @@ -901,6 +901,7 @@ fn (p mut Parser) type_decl() { }) if p.pass == .main { p.cgen.consts << 'const char * __SumTypeNames__${name}[] = {' + p.cgen.consts << ' "$name",' for ctype_name in ctype_names { p.cgen.consts << ' "$ctype_name",' } diff --git a/vlib/compiler/expression.v b/vlib/compiler/expression.v index ba6f974b9e..7b541c5e3c 100644 --- a/vlib/compiler/expression.v +++ b/vlib/compiler/expression.v @@ -831,7 +831,9 @@ fn (p mut Parser) factor() string { is_sum_type := type_of_var in p.table.sum_types if is_sum_type && vname.len > 0 { // TODO: make this work for arbitrary sumtype expressions, not just simple vars - p.gen('${vname}.typ == 0 ? tos3("typeof(): typ == 0") : tos3(__SumTypeNames__${type_of_var}[${vname}.typ - 1])') + // NB: __SumTypeNames__[xxx][0] is the name of the sumtype itself; + // idx>0 are the names of the sumtype children + p.gen('tos3(__SumTypeNames__${type_of_var}[${vname}.typ])') }else{ p.gen('tos3("$type_of_var")') } diff --git a/vlib/v/ast/ast.v b/vlib/v/ast/ast.v index 954eb23911..b11eccb95c 100644 --- a/vlib/v/ast/ast.v +++ b/vlib/v/ast/ast.v @@ -8,6 +8,8 @@ import ( v.table ) +pub type TypeDecl = AliasTypeDecl | SumTypeDecl + pub type Expr = InfixExpr | IfExpr | StringLiteral | IntegerLiteral | CharLiteral | FloatLiteral | Ident | CallExpr | BoolLiteral | StructInit | ArrayInit | SelectorExpr | PostfixExpr | AssignExpr | PrefixExpr | MethodCallExpr | IndexExpr | RangeExpr | MatchExpr | @@ -439,10 +441,18 @@ pub: vals []string } -pub struct TypeDecl { +pub struct AliasTypeDecl { pub: name string is_pub bool + parent_type table.Type +} + +pub struct SumTypeDecl { +pub: + name string + is_pub bool + sub_types []table.Type } pub struct DeferStmt { diff --git a/vlib/v/fmt/fmt.v b/vlib/v/fmt/fmt.v index 08e7e3a6be..f04ac53e4a 100644 --- a/vlib/v/fmt/fmt.v +++ b/vlib/v/fmt/fmt.v @@ -127,7 +127,7 @@ fn (f mut Fmt) stmt(node ast.Stmt) { f.writeln('continue') } else {} - } + } } ast.ConstDecl { if it.is_pub { @@ -245,13 +245,46 @@ fn (f mut Fmt) stmt(node ast.Stmt) { f.expr(it.expr) f.writeln('') } + ast.Import { + // already handled in f.imports + } + ast.TypeDecl { + f.type_decl( it ) + } else { - println('unknown node') + eprintln('fmt stmt: unknown node: ' + typeof(node)) // exit(1) } } } +fn (f mut Fmt) type_decl(node ast.TypeDecl) { + match node { + ast.AliasTypeDecl { + if it.is_pub { + f.write('pub ') + } + ptype := f.table.type_to_str( it.parent_type ) + f.write('type $it.name $ptype') + } + ast.SumTypeDecl { + if it.is_pub { + f.write('pub ') + } + f.write('type $it.name = ') + mut sum_type_names := []string + for t in it.sub_types { + sum_type_names << f.table.type_to_str(t) + } + f.write( sum_type_names.join(' | ') ) + } + else { + eprintln('fmt type_decl: unknown ' + typeof(node)) + } + } + f.writeln('\n') +} + fn (f mut Fmt) struct_decl(node ast.StructDecl) { if node.is_pub { f.write('pub ') @@ -526,7 +559,7 @@ fn (f mut Fmt) expr(node ast.Expr) { } } else { - println('fmt expr: unhandled node ') // + typeof(node)) + eprintln('fmt expr: unhandled node ' + typeof(node)) } } } diff --git a/vlib/v/fmt/fmt_test.v b/vlib/v/fmt/fmt_test.v index 7283d50109..36ef0842eb 100644 --- a/vlib/v/fmt/fmt_test.v +++ b/vlib/v/fmt/fmt_test.v @@ -46,7 +46,7 @@ fn test_fmt() { continue } table := table.new_table() - file_ast := parser.parse_file(ipath, table, .skip_comments) + file_ast := parser.parse_file(ipath, table, .parse_comments) result_ocontent := fmt.fmt(file_ast, table) if expected_ocontent != result_ocontent { fmt_bench.fail() diff --git a/vlib/v/fmt/tests/import_multiple_with_alias_expected.vv b/vlib/v/fmt/tests/import_multiple_with_alias_expected.vv new file mode 100644 index 0000000000..57dee5b720 --- /dev/null +++ b/vlib/v/fmt/tests/import_multiple_with_alias_expected.vv @@ -0,0 +1,5 @@ +import ( + math as m + os + math.complex as c +) diff --git a/vlib/v/fmt/tests/import_multiple_with_alias_input.vv b/vlib/v/fmt/tests/import_multiple_with_alias_input.vv new file mode 100644 index 0000000000..84d4a347a8 --- /dev/null +++ b/vlib/v/fmt/tests/import_multiple_with_alias_input.vv @@ -0,0 +1,3 @@ +import math as m +import os +import math.complex as c diff --git a/vlib/v/fmt/tests/simple_expected.vv b/vlib/v/fmt/tests/simple_expected.vv index 4a81a562d6..848cd425f7 100644 --- a/vlib/v/fmt/tests/simple_expected.vv +++ b/vlib/v/fmt/tests/simple_expected.vv @@ -129,6 +129,8 @@ struct Bar { val int } +type FooBar = Foo | Bar + const ( reserved_types = { 'i8': true diff --git a/vlib/v/fmt/tests/types_expected.vv b/vlib/v/fmt/tests/types_expected.vv new file mode 100644 index 0000000000..a6ef5d4a2b --- /dev/null +++ b/vlib/v/fmt/tests/types_expected.vv @@ -0,0 +1,9 @@ +// Sumtype +type FooBar = Foo | Bar + +pub type PublicBar = Foo | Bar | FooBar + +// Alias type +type MyInt int + +pub type Abc f32 diff --git a/vlib/v/fmt/tests/types_input.vv b/vlib/v/fmt/tests/types_input.vv new file mode 100644 index 0000000000..3293566bd7 --- /dev/null +++ b/vlib/v/fmt/tests/types_input.vv @@ -0,0 +1,10 @@ + + + // Sumtype + type FooBar= Foo | Bar + pub type PublicBar = Foo | Bar | FooBar + + // Alias type + type MyInt int + + pub type Abc f32 diff --git a/vlib/v/parser/parser.v b/vlib/v/parser/parser.v index 013558ca88..ab452f0491 100644 --- a/vlib/v/parser/parser.v +++ b/vlib/v/parser/parser.v @@ -56,7 +56,7 @@ pub fn parse_stmt(text string, table &table.Table, scope &ast.Scope) ast.Stmt { pref: &pref.Preferences{} scope: scope // scope: &ast.Scope{start_pos: 0, parent: 0} - + } p.init_parse_fns() p.read_first_token() @@ -80,7 +80,7 @@ pub fn parse_file(path string, table &table.Table, comments_mode scanner.Comment parent: 0 } // comments_mode: comments_mode - + } p.read_first_token() // p.scope = &ast.Scope{start_pos: p.tok.position(), parent: 0} @@ -614,7 +614,7 @@ pub fn (p mut Parser) name_expr() ast.Expr { p.expr_mod = '' return ast.EnumVal{ enum_name: enum_name // lp.prepend_mod(enum_name) - + val: val pos: p.tok.position() } @@ -941,7 +941,7 @@ fn (p mut Parser) infix_expr(left ast.Expr) ast.Expr { left: left right: right // right_type: typ - + op: op pos: pos } @@ -1052,7 +1052,7 @@ fn (p mut Parser) for_statement() ast.Stmt { p.scope.register_var(ast.VarDecl{ name: var_name // expr: cond - + }) stmts := p.parse_block() // println('nr stmts=$stmts.len') @@ -1147,11 +1147,11 @@ fn (p mut Parser) if_expr() ast.Expr { stmts: stmts else_stmts: else_stmts // typ: typ - + pos: pos has_else: has_else // left: left - + } return node } @@ -1325,7 +1325,7 @@ fn (p mut Parser) const_decl() ast.ConstDecl { fields << ast.Field{ name: name // typ: typ - + } exprs << expr // TODO: once consts are fixed reg here & update in checker @@ -1536,12 +1536,12 @@ fn (p mut Parser) var_decl_and_assign_stmt() ast.Stmt { return ast.VarDecl{ name: ident.name // name2: name2 - + expr: expr // p.expr(token.lowest_prec) - + is_mut: info0.is_mut // typ: typ - + pos: p.tok.position() } // return p.var_decl(ident[0], exprs[0]) @@ -1714,8 +1714,8 @@ fn (p mut Parser) type_decl() ast.TypeDecl { p.check(.key_type) name := p.check_name() mut sum_variants := []table.Type - // type SumType = A | B | c if p.tok.kind == .assign { + // type SumType = A | B | c p.next() for { variant_type := p.parse_type() @@ -1732,21 +1732,28 @@ fn (p mut Parser) type_decl() ast.TypeDecl { variants: sum_variants } }) + return ast.SumTypeDecl{ + name: name + is_pub: is_pub + sub_types: sum_variants + } } + // type MyType int - else { - parent_type := p.parse_type() - p.table.register_type_symbol(table.TypeSymbol{ - kind: .alias - name: p.prepend_mod(name) - parent_idx: table.type_idx(parent_type) - info: table.Alias{ - foo: '' - } - }) - } - return ast.TypeDecl{ + parent_type := p.parse_type() + pid := table.type_idx(parent_type) + p.table.register_type_symbol(table.TypeSymbol{ + kind: .alias + name: p.prepend_mod(name) + parent_idx: pid + info: table.Alias{ + foo: '' + } + }) + return ast.AliasTypeDecl{ name: name + is_pub: is_pub + parent_type: parent_type } } diff --git a/vlib/v/table/atype_symbols.v b/vlib/v/table/atype_symbols.v index cbb866e7f1..c272ee13dc 100644 --- a/vlib/v/table/atype_symbols.v +++ b/vlib/v/table/atype_symbols.v @@ -7,7 +7,7 @@ import ( strings ) -pub type TypeInfo = Array | ArrayFixed | Map | Struct | +pub type TypeInfo = Array | ArrayFixed | Map | Struct | MultiReturn | Alias | Enum | SumType pub struct TypeSymbol { @@ -344,8 +344,18 @@ pub fn (k Kind) str() string { .multi_return{ 'multi_return' } + .sum_type{ + 'sum_type' + } + .alias{ + 'alias' + } + .enum_{ + 'enum' + } else { - 'unknown'} + 'unknown' + } } return k_str } @@ -405,6 +415,7 @@ pub mut: } pub struct SumType { +pub: variants []Type }