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
|
||||||
import v.util.version
|
import v.util.version
|
||||||
import v.depgraph
|
import v.depgraph
|
||||||
|
import analysis
|
||||||
|
|
||||||
|
|
||||||
[heap]
|
[heap]
|
||||||
|
@ -107,12 +107,28 @@ fn (mut fc FuncContext) new_variable_with_level(name_ string, mod_level bool) st
|
|||||||
return var_name
|
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 {
|
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 {
|
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.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
|
fc.mod_ctx.object_names[o] = name
|
||||||
name
|
name
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user