mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
newjs: sideeffect, break and escape analysis (W.I.P)
This commit is contained in:
parent
9231661b86
commit
13dbb0ec28
34
vlib/v/gen/newjs/analysis/break.v
Normal file
34
vlib/v/gen/newjs/analysis/break.v
Normal file
@ -0,0 +1,34 @@
|
||||
module analysis
|
||||
|
||||
import v.ast
|
||||
import v.ast.walker
|
||||
|
||||
struct HasBreakVisitor {
|
||||
mut:
|
||||
has_break bool
|
||||
}
|
||||
|
||||
pub fn has_break(n &ast.Node) bool {
|
||||
mut v := HasBreakVisitor{has_break: false}
|
||||
walker.walk(mut v, n)
|
||||
return v.has_break
|
||||
}
|
||||
|
||||
fn (mut v HasBreakVisitor) visit(node &ast.Node) ! {
|
||||
if v.has_break {
|
||||
return
|
||||
}
|
||||
|
||||
if node is ast.Stmt {
|
||||
match node {
|
||||
ast.BranchStmt {
|
||||
if node.kind == .key_break && node.label.len > 0 {
|
||||
v.has_break = true
|
||||
return
|
||||
}
|
||||
}
|
||||
else {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
102
vlib/v/gen/newjs/analysis/escape.v
Normal file
102
vlib/v/gen/newjs/analysis/escape.v
Normal file
@ -0,0 +1,102 @@
|
||||
module analysis
|
||||
|
||||
import v.ast
|
||||
import v.ast.walker
|
||||
|
||||
|
||||
pub fn escaping_objects(n &ast.Node) []&ast.Var {
|
||||
mut v := EscapeAnalysis {
|
||||
escaping: map[voidptr]bool{}
|
||||
bottom_scopes: map[voidptr]bool{}
|
||||
}
|
||||
|
||||
walker.walk(mut v, n)
|
||||
|
||||
mut list := []&ast.Var{}
|
||||
|
||||
for obj, _ in v.escaping {
|
||||
list << &ast.Var(obj)
|
||||
}
|
||||
|
||||
return list
|
||||
}
|
||||
|
||||
struct EscapeAnalysis {
|
||||
mut:
|
||||
escaping map[voidptr]bool
|
||||
top_scope &ast.Scope = unsafe { nil }
|
||||
bottom_scopes map[voidptr]bool
|
||||
|
||||
}
|
||||
|
||||
fn (mut v EscapeAnalysis) visit(node &ast.Node) ! {
|
||||
match node {
|
||||
ast.Expr {
|
||||
if node is ast.PostfixExpr {
|
||||
if node.op == .amp {
|
||||
if node.expr is ast.Ident {
|
||||
mut collector := EscapingObjectCollector {
|
||||
analysis: unsafe { v }
|
||||
}
|
||||
walker.walk(mut collector, &ast.Node(ast.Expr(node.expr)))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ast.Stmt {
|
||||
match node {
|
||||
ast.FnDecl {
|
||||
v.bottom_scopes[voidptr(node.scope)] = true
|
||||
mut collector := EscapingObjectCollector {
|
||||
analysis: unsafe { v }
|
||||
}
|
||||
walker.walk(mut collector, &ast.Node(ast.Stmt(node)))
|
||||
return
|
||||
}
|
||||
|
||||
ast.ForStmt {
|
||||
v.bottom_scopes[voidptr(node.scope)] = true
|
||||
return
|
||||
}
|
||||
|
||||
else {
|
||||
return
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct EscapingObjectCollector {
|
||||
mut:
|
||||
analysis &EscapeAnalysis
|
||||
}
|
||||
|
||||
fn (mut v EscapingObjectCollector) visit(node &ast.Node) ! {
|
||||
if node is ast.Expr {
|
||||
match node {
|
||||
ast.Ident {
|
||||
if node.obj is ast.Var {
|
||||
mut s := node.scope
|
||||
|
||||
for unsafe { s != nil } {
|
||||
if s == v.analysis.top_scope {
|
||||
v.analysis.escaping[voidptr(unsafe { &node })] = true
|
||||
break
|
||||
}
|
||||
|
||||
if v.analysis.bottom_scopes[voidptr(s)] {
|
||||
break
|
||||
}
|
||||
s = s.parent
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
39
vlib/v/gen/newjs/analysis/sideeffect.v
Normal file
39
vlib/v/gen/newjs/analysis/sideeffect.v
Normal file
@ -0,0 +1,39 @@
|
||||
module analysis
|
||||
|
||||
import v.ast
|
||||
import v.ast.walker
|
||||
|
||||
struct HasSideEffectVisitor {
|
||||
mut:
|
||||
has_sideeffect bool
|
||||
}
|
||||
|
||||
pub fn has_sideeffect(n &ast.Node) bool {
|
||||
mut v := HasSideEffectVisitor{has_sideeffect: false}
|
||||
walker.walk(mut v, n)
|
||||
return v.has_sideeffect
|
||||
}
|
||||
|
||||
fn (mut v HasSideEffectVisitor) visit(node &ast.Node) ! {
|
||||
if v.has_sideeffect {
|
||||
return
|
||||
}
|
||||
|
||||
if node is ast.Expr {
|
||||
match node {
|
||||
ast.InfixExpr {
|
||||
if node.op == .arrow {
|
||||
v.has_sideeffect = true
|
||||
return
|
||||
}
|
||||
}
|
||||
ast.CallExpr {
|
||||
v.has_sideeffect = true
|
||||
return
|
||||
}
|
||||
// todo: overloaded operators can lead to side effects as well?
|
||||
else {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
30
vlib/v/gen/newjs/expression.v
Normal file
30
vlib/v/gen/newjs/expression.v
Normal file
@ -0,0 +1,30 @@
|
||||
module newjs
|
||||
|
||||
import strings
|
||||
import v.ast
|
||||
import v.token
|
||||
import v.pref
|
||||
import v.util
|
||||
import v.util.version
|
||||
import v.depgraph
|
||||
|
||||
[heap]
|
||||
struct Expression {
|
||||
str string
|
||||
parens bool
|
||||
}
|
||||
|
||||
fn (e &Expression) str() string {
|
||||
return e.str
|
||||
}
|
||||
|
||||
fn (e &Expression) str_with_parens() string {
|
||||
if e.parens {
|
||||
return '(' + e.str + ')'
|
||||
}
|
||||
return e.str
|
||||
}
|
||||
|
||||
fn (mut fc FuncContext) translate_expr(expr ast.Expr) &Expression {
|
||||
return unsafe { nil }
|
||||
}
|
@ -7,6 +7,7 @@ import v.pref
|
||||
import v.util
|
||||
import v.util.version
|
||||
import v.depgraph
|
||||
import analysis
|
||||
|
||||
|
||||
[heap]
|
||||
|
@ -107,12 +107,28 @@ fn (mut fc FuncContext) new_variable_with_level(name_ string, mod_level bool) st
|
||||
return var_name
|
||||
}
|
||||
|
||||
fn (mut fc FuncContext) new_ident(name string, t ast.Type) {
|
||||
|
||||
}
|
||||
/*
|
||||
fn (mut fc FuncContext) new_ident(name string, t ast.Type) &ast.Ident {
|
||||
id := &ast.Ident {
|
||||
language: .js
|
||||
tok_kind: .name
|
||||
comptime: false
|
||||
mod: fc.mod_ctx.mod.name
|
||||
name: name
|
||||
kind: .variable
|
||||
info: IdentVar {
|
||||
typ: t
|
||||
is_mut: true
|
||||
is_static: false
|
||||
is_volatile: false
|
||||
is_optional: false
|
||||
share: .mut_t
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
fn is_mod_level(fc &FuncContext, sym &ast.Ident) bool {
|
||||
return unsafe { sym.scope is nil || (sym.scope == fc.mod_ctx.gen.table.global_scope || sym.scope.parent == fc.mod_ctx.gen.table.global_scope) }
|
||||
return unsafe { sym.scope == nil || (sym.scope == fc.mod_ctx.gen.table.global_scope || sym.scope.parent == fc.mod_ctx.gen.table.global_scope) }
|
||||
}
|
||||
|
||||
fn (mut fc FuncContext) ident_name(o &ast.Ident) string {
|
||||
@ -125,7 +141,7 @@ fn (mut fc FuncContext) ident_name(o &ast.Ident) string {
|
||||
}
|
||||
|
||||
name := fc.mod_ctx.object_names[o] or {
|
||||
name := fc.new_variable_with_level(o.name, is_mod_level(o))
|
||||
name := fc.new_variable_with_level(o.name, is_mod_level(fc, o))
|
||||
fc.mod_ctx.object_names[o] = name
|
||||
name
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user