cgen: enum str()

pull/4291/head
Daniel Däschle 2020-04-08 15:54:38 +02:00 committed by GitHub
parent 1388532bd4
commit 6bba7d4e3a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 127 additions and 18 deletions

View File

@ -17,7 +17,7 @@ indent_size = 2
[*.md] [*.md]
trim_trailing_whitespace = false trim_trailing_whitespace = false
[*.txt] [*.{txt,out}]
insert_final_newline = false insert_final_newline = false
[Makefile] [Makefile]

View File

@ -367,7 +367,7 @@ fn (g mut Gen) stmt(node ast.Stmt) {
g.expr(it.default_exprs[j]) g.expr(it.default_exprs[j])
expr := g.out.after(pos) expr := g.out.after(pos)
g.out.go_back(expr.len) g.out.go_back(expr.len)
g.typedefs.writeln('$expr ,') g.typedefs.writeln('$expr,')
} else { } else {
g.typedefs.writeln('\t${name}_$val, // $j') g.typedefs.writeln('\t${name}_$val, // $j')
} }
@ -1210,10 +1210,10 @@ fn (g mut Gen) typeof_expr(node ast.TypeOf) {
fn (g mut Gen) enum_expr(node ast.Expr) { fn (g mut Gen) enum_expr(node ast.Expr) {
match node { match node {
ast.EnumVal { ast.EnumVal {
g.write('$it.val.capitalize()') g.write(it.val)
} }
else { else {
println(term.red('cgen.enum_expr(): bad node ' + typeof(node))) g.expr(node)
} }
} }
} }
@ -2260,6 +2260,7 @@ fn (g mut Gen) string_inter_literal(node ast.StringInterLiteral) {
// } // }
// else {} // else {}
// } // }
sym := g.table.get_type_symbol(node.expr_types[i])
sfmt := node.expr_fmts[i] sfmt := node.expr_fmts[i]
if sfmt.len > 0 { if sfmt.len > 0 {
fspec := sfmt[sfmt.len - 1] fspec := sfmt[sfmt.len - 1]
@ -2267,10 +2268,13 @@ fn (g mut Gen) string_inter_literal(node ast.StringInterLiteral) {
verror('only V strings can be formatted with a ${sfmt} format') verror('only V strings can be formatted with a ${sfmt} format')
} }
g.write('%' + sfmt[1..]) g.write('%' + sfmt[1..])
} else if node.expr_types[i] == table.string_type || node.expr_types[i] == table.bool_type { } else if node.expr_types[i] in [table.string_type, table.bool_type] || sym.kind == .enum_ {
g.write('%.*s') g.write('%.*s')
} else { } else {
g.write('%d') match node.exprs[i] {
ast.EnumVal { g.write('%.*s') }
else { g.write('%d') }
}
} }
} }
g.write('", ') g.write('", ')
@ -2297,7 +2301,39 @@ fn (g mut Gen) string_inter_literal(node ast.StringInterLiteral) {
g.expr(expr) g.expr(expr)
g.write(' ? "true" : "false"') g.write(' ? "true" : "false"')
} else { } else {
g.expr(expr) sym := g.table.get_type_symbol(node.expr_types[i])
if sym.kind == .enum_ {
is_var := match node.exprs[i] {
ast.SelectorExpr { true }
ast.Ident { true }
else { false }
}
if is_var {
styp := g.typ(node.expr_types[i])
if !sym.has_method('str') && !(styp in g.str_types) {
// Generate an automatic str() method if this type doesn't have it already
g.str_types << styp
g.gen_str_for_type(sym, styp)
}
g.write('${styp}_str(')
g.enum_expr(expr)
g.write(')')
g.write('.len, ')
g.write('${styp}_str(')
g.enum_expr(expr)
g.write(').str')
} else {
g.write('tos3("')
g.enum_expr(expr)
g.write('")')
g.write('.len, ')
g.write('"')
g.enum_expr(expr)
g.write('"')
}
} else {
g.expr(expr)
}
} }
if i < node.exprs.len - 1 { if i < node.exprs.len - 1 {
g.write(', ') g.write(', ')
@ -2466,9 +2502,15 @@ fn (g mut Gen) fn_call(node ast.CallExpr) {
g.expr(node.args[0].expr) g.expr(node.args[0].expr)
g.writeln('); ${print_method}($tmp); string_free($tmp); //MEM2 $styp') g.writeln('); ${print_method}($tmp); string_free($tmp); //MEM2 $styp')
} else if sym.kind == .enum_ { } else if sym.kind == .enum_ {
g.write('${print_method}(tos3("') expr := node.args[0].expr
g.enum_expr(node.args[0].expr) is_var := match expr {
g.write('"))') ast.SelectorExpr { true }
ast.Ident { true }
else { false }
}
g.write(if is_var { '${print_method}(${styp}_str(' } else { '${print_method}(tos3("' })
g.enum_expr(expr)
g.write(if is_var { '))' } else { '"))' })
} else { } else {
// `println(int_str(10))` // `println(int_str(10))`
// sym := g.table.get_type_symbol(node.args[0].typ) // sym := g.table.get_type_symbol(node.args[0].typ)
@ -2962,15 +3004,32 @@ fn (g mut Gen) go_stmt(node ast.GoStmt) {
// already generated styp, reuse it // already generated styp, reuse it
fn (g mut Gen) gen_str_for_type(sym table.TypeSymbol, styp string) { fn (g mut Gen) gen_str_for_type(sym table.TypeSymbol, styp string) {
s := styp.replace('.', '__')
match sym.info { match sym.info {
table.Struct {} table.Struct {
g.gen_str_for_struct(it, styp)
}
table.Enum {
g.gen_str_for_enum(it, styp)
}
else { else {
println('str() not a struct $sym.name') println('cannot generate str() for $sym.name')
return
} }
} }
info := sym.info as table.Struct }
fn (g mut Gen) gen_str_for_enum(info table.Enum, styp string) {
s := styp.replace('.', '__')
g.definitions.write('string ${s}_str($styp a) {\n\tswitch(a) {\n')
for i, expr in info.default_exprs {
val := info.vals[i]
int_expr := expr as ast.IntegerLiteral
g.definitions.write('\t\tcase $int_expr.val: return tos3("$val");\n')
}
g.definitions.write('\t\tdefault: return tos3("unknown enum value"); } }\n')
}
fn (g mut Gen) gen_str_for_struct(info table.Struct, styp string) {
s := styp.replace('.', '__')
g.definitions.write('string ${s}_str($styp a) { return _STR("$styp {\\n') g.definitions.write('string ${s}_str($styp a) { return _STR("$styp {\\n')
for field in info.fields { for field in info.fields {
fmt := type_to_fmt(field.typ) fmt := type_to_fmt(field.typ)

View File

@ -1873,6 +1873,7 @@ fn (p mut Parser) enum_decl() ast.EnumDecl {
name: name name: name
info: table.Enum{ info: table.Enum{
vals: vals vals: vals
default_exprs: default_exprs
} }
}) })
return ast.EnumDecl{ return ast.EnumDecl{

View File

@ -14,6 +14,7 @@ module table
import ( import (
strings strings
v.ast
) )
pub type Type int pub type Type int
@ -546,6 +547,7 @@ pub mut:
pub struct Enum { pub struct Enum {
pub mut: pub mut:
vals []string vals []string
default_exprs []ast.Expr
} }
pub struct Alias { pub struct Alias {

View File

@ -0,0 +1,5 @@
yellow
green
green
interp: green
interp: green

View File

@ -0,0 +1,21 @@
module main
enum Color {
green = 5
red = 2
yellow = 1
}
struct A{
color Color
}
fn main() {
col := Color.green
a := A{color: col}
println(Color.yellow)
println(col)
println(a.color)
println('interp: ${col}')
println('interp: ${a.color}')
}

View File

@ -0,0 +1,21 @@
module main
enum Color {
green = 5
red = 2
yellow = 1
}
struct A{
color Color
}
fn main() {
col := Color.green
a := A{color: col}
println(Color.yellow)
println(col)
println(a.color)
println('interp: ${col}')
println('interp: ${a.color}')
}

View File

@ -1 +1 @@
hello world hello world

View File

@ -3,4 +3,4 @@ Hello, web developers!
Hello, tools developers! Hello, tools developers!
Hello, science developers! Hello, science developers!
Hello, systems developers! Hello, systems developers!
Hello, embedded developers! Hello, embedded developers!

View File

@ -1,4 +1,4 @@
CHANGELOG.md CHANGELOG.md
CODE_OF_CONDUCT.md CODE_OF_CONDUCT.md
CONTRIBUTING.md CONTRIBUTING.md
README.md README.md