new vfmt using the new parser

pull/3763/head
Alexander Medvednikov 2020-02-17 22:50:04 +01:00
parent a2838ae6f3
commit 59beec8fae
6 changed files with 359 additions and 38 deletions

View File

@ -8,14 +8,23 @@ import (
v.table
)
pub type Expr = InfixExpr | IfExpr | StringLiteral | IntegerLiteral | CharLiteral |
FloatLiteral | Ident | CallExpr | BoolLiteral | StructInit | ArrayInit | SelectorExpr | PostfixExpr |
AssignExpr | PrefixExpr | MethodCallExpr | IndexExpr | RangeExpr | MatchExpr |
pub type Expr = InfixExpr | IfExpr | StringLiteral | IntegerLiteral | CharLiteral |
FloatLiteral | Ident | CallExpr | BoolLiteral | StructInit | ArrayInit | SelectorExpr | PostfixExpr |
AssignExpr | PrefixExpr | MethodCallExpr | IndexExpr | RangeExpr | MatchExpr |
CastExpr | EnumVal
pub type Stmt = VarDecl | GlobalDecl | FnDecl | Return | Module | Import | ExprStmt |
ForStmt | StructDecl | ForCStmt | ForInStmt | CompIf | ConstDecl | Attr | BranchStmt |
pub type Stmt = VarDecl | GlobalDecl | FnDecl | Return | Module | Import | ExprStmt |
ForStmt | StructDecl | ForCStmt | ForInStmt | CompIf | ConstDecl | Attr | BranchStmt |
HashStmt | AssignStmt | EnumDecl | TypeDecl | DeferStmt | GotoLabel | GotoStmt
pub type Type = StructType | ArrayType
pub struct StructType {
fields []Field
}
pub struct ArrayType {}
// | IncDecStmt k
// Stand-alone expression in a statement list.
pub struct ExprStmt {
@ -72,6 +81,7 @@ pub:
// type_idx int
mut:
typ table.Type
// typ2 Type
}
pub struct ConstDecl {
@ -194,11 +204,11 @@ pub:
pub struct File {
pub:
path string
mod Module
imports []Import
stmts []Stmt
scope Scope
path string
mod Module
imports []Import
stmts []Stmt
scope Scope
}
pub struct IdentFunc {
@ -387,15 +397,15 @@ pub:
vals []string
}
pub struct TypeDecl{
pub struct TypeDecl {
pub:
name string
is_pub bool
}
pub struct DeferStmt{
pub struct DeferStmt {
pub:
stmts []Stmt
stmts []Stmt
}
pub struct AssignExpr {
@ -406,14 +416,14 @@ pub:
val Expr
}
pub struct GotoLabel{
pub struct GotoLabel {
pub:
name string
name string
}
pub struct GotoStmt {
pub:
name string
name string
}
pub struct ArrayInit {

View File

@ -3,7 +3,24 @@
// that can be found in the LICENSE file.
module fmt
import (
v.ast
v.table
strings
)
const (
tabs = ['', '\t', '\t\t', '\t\t\t', '\t\t\t\t']
// tabs = ['', ' ', ' ', ' ', ' ']
)
struct Fmt {
out strings.Builder
table &table.Table
mut:
indent int
empty_line bool
/*
// vfmt fields TODO move to a separate struct
// fmt_out strings.Builder
fmt_lines []string
@ -11,5 +28,239 @@ struct Fmt {
fmt_indent int
fmt_line_empty bool
// fmt_needs_nl bool
*/
}
pub fn fmt(file ast.File, table &table.Table) {
mut f := Fmt{
out: strings.new_builder(1000)
table: table
indent: -1
}
f.stmts(file.stmts)
println('!!!!!!!!!')
println(f.out.str())
}
pub fn (f mut Fmt) write(s string) {
if f.indent > 0 && f.empty_line {
f.out.write(tabs[f.indent])
f.empty_line = false
}
f.out.write(s)
}
pub fn (f mut Fmt) writeln(s string) {
if f.indent > 0 {
println(f.indent.str() + s)
f.out.write(tabs[f.indent])
}
f.out.writeln(s)
f.empty_line = true
}
fn (f mut Fmt) stmts(stmts []ast.Stmt) {
f.indent++
for stmt in stmts {
f.stmt(stmt)
}
f.indent--
}
fn (f mut Fmt) stmt(node ast.Stmt) {
match node {
ast.AssignStmt {
for i, left in it.left {
f.expr(left)
if i < it.left.len - 1 {
f.write(', ')
}
}
f.write(' = ')
for right in it.right {
f.expr(right)
}
}
ast.ConstDecl {
f.writeln('const (')
f.indent++
for i, field in it.fields {
f.write('$field.name = ')
f.expr(it.exprs[i])
}
f.indent--
f.writeln('\n)\n')
}
ast.ExprStmt {
f.expr(it.expr)
f.writeln('')
}
ast.FnDecl {
f.writeln('fn ${it.name}() {')
f.stmts(it.stmts)
f.writeln('}\n')
}
ast.Return {
f.write('return')
// multiple returns
if it.exprs.len > 1 {
for i, expr in it.exprs {
f.expr(expr)
if i < it.exprs.len - 1 {
f.write(', ')
}
}
}
// normal return
else if it.exprs.len == 1 {
f.write(' ')
f.expr(it.exprs[0])
}
f.writeln('')
}
ast.StructDecl {
f.struct_decl(it)
}
ast.VarDecl {
// type_sym := f.table.get_type_symbol(it.typ)
if it.is_mut {
f.write('mut ')
}
f.write('$it.name := ')
f.expr(it.expr)
f.writeln('')
}
else {
println('unknown node')
// exit(1)
}
}
}
fn (f mut Fmt) struct_decl(node ast.StructDecl) {
f.writeln('struct $node.name {')
mut max := 0
for field in node.fields {
if field.name.len > max {
max = field.name.len
}
}
for field in node.fields {
field_type_sym := f.table.get_type_symbol(field.typ)
f.write('\t$field.name ')
f.write(strings.repeat(` `, max - field.name.len))
f.writeln('$field_type_sym.name')
}
f.writeln('}\n')
}
fn (f mut Fmt) expr(node ast.Expr) {
match node {
ast.ArrayInit {
// type_sym := f.table.get_type_symbol(it.typ)
f.write('[')
for i, expr in it.exprs {
f.expr(expr)
if i < it.exprs.len - 1 {
f.write(', ')
}
}
f.write(']')
}
ast.AssignExpr {
f.expr(it.left)
f.write(' $it.op.str() ')
f.expr(it.val)
}
ast.BoolLiteral {
f.write(it.val.str())
}
ast.CallExpr {
f.write('${it.name}(')
for i, expr in it.args {
f.expr(expr)
if i != it.args.len - 1 {
f.write(', ')
}
}
f.write(')')
}
ast.FloatLiteral {
f.write(it.val)
}
ast.IfExpr {
f.write('if ')
f.expr(it.cond)
f.writeln('{')
f.stmts(it.stmts)
f.writeln('}')
if it.else_stmts.len > 0 {
f.writeln('else { ')
f.stmts(it.else_stmts)
f.writeln('}')
}
}
ast.Ident {
f.write('$it.name')
}
ast.InfixExpr {
f.expr(it.left)
f.write(' $it.op.str() ')
f.expr(it.right)
}
ast.IndexExpr {
f.index_expr(it)
}
ast.IntegerLiteral {
f.write(it.val.str())
}
ast.PostfixExpr {
f.expr(it.expr)
f.write(it.op.str())
}
ast.PrefixExpr {
f.write(it.op.str())
f.expr(it.right)
}
ast.SelectorExpr {
f.expr(it.expr)
f.write('.')
f.write(it.field)
}
ast.StringLiteral {
f.write('"$it.val"')
}
ast.StructInit {
type_sym := f.table.get_type_symbol(it.typ)
f.writeln('$type_sym.name{')
for i, field in it.fields {
f.write('\t$field: ')
f.expr(it.exprs[i])
f.writeln('')
}
f.write('}')
}
else {}
}
}
fn (f mut Fmt) index_expr(node ast.IndexExpr) {
mut is_range := false
match node.index {
ast.RangeExpr {
is_range = true
f.expr(node.left)
f.write('..')
f.expr(it.high)
f.write(')')
}
else {}
}
if !is_range {
f.expr(node.left)
f.write('[')
f.expr(node.index)
f.write(']')
}
}

View File

@ -0,0 +1,31 @@
import (
os
v.fmt
filepath
term
v.table
v.parser
)
const (
nr_tests = 1
)
fn test_fmt() {
println('Running vfmt tests')
vexe := os.getenv('VEXE')
vroot := filepath.dir(vexe)
term_ok := term.ok_message('OK')
term_fail := term.fail_message('FAIL')
for i in 1 .. nr_tests + 1 {
path := '$vroot/vlib/v/fmt/tests/${i}.vv'
println(path)
mut ctext := os.read_file('$vroot/vlib/v/fmt/tests/${i}_out.vv') or {
panic(err)
}
ctext = ctext // unused warn
table := table.new_table()
file := parser.parse_file(path, table)
fmt.fmt(file, table)
}
}

View File

@ -0,0 +1,37 @@
fn hello()
{
mut a:= 3 + 3
a = 10
a++
-23
b:= 42
println( 'hello' )
abc()
if true {
a = 10
a++
} else {
println('false')
}
}
const (
pi=3.14
)
struct User {
name string
age int
very_long_field bool
}
fn abc() int {
mut u := User{name:'Bob'}
u.age = 20
nums := [1,2,3]
number := nums[0]
return 0
}

View File

View File

@ -24,10 +24,7 @@ pub fn cgen(files []ast.File, table &table.Table) string {
fn_decl: 0
}
for file in files {
for stmt in file.stmts {
g.stmt(stmt)
g.writeln('')
}
g.stmts(file.stmts)
}
return g.definitions.str() + g.out.str()
}
@ -76,7 +73,7 @@ fn (g mut Gen) stmt(node ast.Stmt) {
for i, arg in it.args {
arg_type_sym := g.table.get_type_symbol(arg.typ)
mut arg_type_name := arg_type_sym.name
if i == it.args.len-1 && it.is_variadic {
if i == it.args.len - 1 && it.is_variadic {
arg_type_name = 'variadic_$arg_type_sym.name'
}
g.write(arg_type_name + ' ' + arg.name)
@ -194,11 +191,23 @@ fn (g mut Gen) stmt(node ast.Stmt) {
fn (g mut Gen) expr(node ast.Expr) {
// println('cgen expr()')
match node {
ast.ArrayInit {
type_sym := g.table.get_type_symbol(it.typ)
g.writeln('new_array_from_c_array($it.exprs.len, $it.exprs.len, sizeof($type_sym.name), {\t')
for expr in it.exprs {
g.expr(expr)
g.write(', ')
}
g.write('\n})')
}
ast.AssignExpr {
g.expr(it.left)
g.write(' $it.op.str() ')
g.expr(it.val)
}
ast.BoolLiteral {
g.write(it.val.str())
}
ast.IntegerLiteral {
g.write(it.val.str())
}
@ -263,26 +272,9 @@ fn (g mut Gen) expr(node ast.Expr) {
g.write(')')
}
ast.MethodCallExpr {}
ast.ArrayInit {
type_sym := g.table.get_type_symbol(it.typ)
g.writeln('new_array_from_c_array($it.exprs.len, $it.exprs.len, sizeof($type_sym.name), {\t')
for expr in it.exprs {
g.expr(expr)
g.write(', ')
}
g.write('\n})')
}
ast.Ident {
g.write('$it.name')
}
ast.BoolLiteral {
if it.val == true {
g.write('true')
}
else {
g.write('false')
}
}
ast.SelectorExpr {
g.expr(it.expr)
g.write('.')