Skip to content

Commit

Permalink
Merge pull request #1430 from GaijinEntertainment/towards_safe_tables
Browse files Browse the repository at this point in the history
WIP: unsafe table lookups
  • Loading branch information
borisbat authored Dec 10, 2024
2 parents e5b16ed + 6fa7d07 commit da3d78f
Show file tree
Hide file tree
Showing 22 changed files with 548 additions and 99 deletions.
2 changes: 1 addition & 1 deletion daslib/json.das
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@ def private parse_value ( var itv : iterator<TokenAt>; var error : string & ) :
if !allow_duplicate_keys && key_exists(tab,key)
error = "duplicate key {key} at {ahead.line}:{ahead.row}"
return null
tab[key] = value
tab |> insert(key,value)
if !expect_token(itv, ahead, Token_symbol, error)
return null
let sepsym = ahead.value as _symbol
Expand Down
3 changes: 2 additions & 1 deletion daslib/macro_boost.das
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@ class CaptureBlock : AstVisitor
return
let vptr = get_ptr(expr.variable)
if !(scope |> key_exists(vptr))
captured[vptr] = unsafe(reinterpret<ExprVar?> get_ptr(expr))
unsafe
captured[vptr] = reinterpret<ExprVar?> get_ptr(expr)
def override preVisitExprLetVariable(expr:smart_ptr<ExprLet>;arg:VariablePtr;lastArg:bool) : void
scope |> insert(get_ptr(arg))
def override preVisitExprForVariable(expr:smart_ptr<ExprFor>;svar:VariablePtr;last:bool) : void
Expand Down
64 changes: 32 additions & 32 deletions daslib/templates_boost.das
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,15 @@ struct Template
def kaboomVarField ( var self:Template; name,prefix,suffix:string )
//! Adds a rule to to the template to replace a variable field access with a prefix and suffix.
//! I.e. foo.bar into prefix + bar + suffix
self.kaboomVar[name] = [[auto prefix,suffix]]
self.kaboomVar |> emplace(name, [[auto prefix,suffix]])

def replaceVariable ( var self:Template; name:string; var expr : smart_ptr<ast::Expression> )
//! Adds a rule to the template to replace a variable with an expression.
move(self.var2expr[name], expr)
self.var2expr |> emplace(name, expr)

def replaceVarTag ( var self:Template; name:string; var expr : smart_ptr<ast::Expression> )
//! Adds a rule to the template to replace a variable tag with an expression.
move(self.tag2expr[name], expr)
self.tag2expr |> emplace(name, expr)

def replaceArgumentWithList ( var self:Template; name:string; blka:array<VariablePtr> )
//! Adds a rule to the template to replace a block argument with a list of variables.
Expand All @@ -55,43 +55,43 @@ def replaceVariableWithList ( var self:Template; name:string; expr : dasvector`s

def renameVariable ( var self:Template; name, newName:string )
//! Adds a rule to the template to rename a variable.
self.var2name[name] = newName
self.var2name |> insert(name, newName)

def renameVariable ( var self:Template; name:string; newName:das_string )
//! Adds a rule to the template to rename a variable.
self.var2name[name] = string(newName)
self.var2name |> insert(name, string(newName))

def renameField ( var self:Template; name, newName:string )
//! Adds a rule to the template to rename any field lookup (., ?., as, is, etc)
self.field2name[name] = newName
self.field2name |> insert(name, newName)

def renameField ( var self:Template; name:string; newName:das_string )
//! Adds a rule to the template to rename any field lookup (., ?., as, is, etc)
self.field2name[name] = string(newName)
self.field2name |> insert(name, string(newName))

def replaceType ( var self:Template; name,newName:string )
//! Adds a rule to the template to replace a type alias with another type alias, specified by name.
self.type2type[name] = newName
self.type2type |> insert(name, newName)

def replaceTypeWithTypeDecl ( var self:Template; name:string; var expr : TypeDeclPtr )
//! Adds a rule to the template to replace a type alias with another type alias, specified by type declaration.
move(self.type2etype[name], expr)
self.type2etype |> emplace(name, expr)

def replaceAnnotationArgument ( var self:Template; name:string; var cb:lambda<(var ann: AnnotationDeclaration):void> )
//! Adds a rule to the template to replace an annotation argument with the result of a callback.
self.annArg[name] <- cb
self.annArg |> emplace(name, cb)

def replaceBlockArgument ( var self:Template; name,newName:string )
//! Adds a rule to the template to rename a block argument.
self.blockArgName[name] = newName
self.blockArgName |> insert(name, newName)

def renameCall ( var self:Template; name, newName:string )
//! Adds a rule to the template to rename a call.
self.call2name[name] = newName
self.call2name |> insert(name, newName)

def renameCall ( var self:Template; name:string; newName:das_string )
//! Adds a rule to the template to rename a call.
self.call2name[name] = string(newName)
self.call2name |> insert(name, string(newName))

class private TemplateVisitor : AstVisitor
[[do_not_delete]] rules : Template?
Expand All @@ -102,38 +102,38 @@ class private TemplateVisitor : AstVisitor
if expr.subexpr is ExprVar
let tn = string((expr.subexpr as ExprVar).name)
if key_exists(rules.tag2expr, tn)
var inscope rexpr <- clone_expression(rules.tag2expr[tn])
var inscope rexpr <- clone_expression(unsafe(rules.tag2expr[tn]))
rexpr.at = expr.at
return <- rexpr
return <- expr
def override preVisitExprMakeStructField(expr:smart_ptr<ExprMakeStruct>;index:int;var decl:MakeFieldDeclPtr;last:bool) : void
let fname = string(decl.name)
if rules.field2name |> key_exists(fname)
decl.name := rules.field2name[fname]
decl.name := rules.field2name |> get_value(fname)
def override visitExprIsVariant(var expr:smart_ptr<ExprIsVariant>) : ExpressionPtr
let fname = string(expr.name)
if rules.field2name |> key_exists(fname)
expr.name := rules.field2name[fname]
expr.name := rules.field2name |> get_value(fname)
return <- expr
def override visitExprAsVariant(var expr:smart_ptr<ExprAsVariant>) : ExpressionPtr
let fname = string(expr.name)
if rules.field2name |> key_exists(fname)
expr.name := rules.field2name[fname]
expr.name := rules.field2name |> get_value(fname)
return <- expr
def override visitExprSafeAsVariant(var expr:smart_ptr<ExprSafeAsVariant>) : ExpressionPtr
let fname = string(expr.name)
if rules.field2name |> key_exists(fname)
expr.name := rules.field2name[fname]
expr.name := rules.field2name |> get_value(fname)
return <- expr
def override visitExprSafeField(var expr:smart_ptr<ExprSafeField>) : ExpressionPtr
let fname = string(expr.name)
if rules.field2name |> key_exists(fname)
expr.name := rules.field2name[fname]
expr.name := rules.field2name |> get_value(fname)
return <- expr
def override visitExprField(var expr:smart_ptr<ExprField>) : ExpressionPtr
let fname = string(expr.name)
if rules.field2name |> key_exists(fname)
expr.name := rules.field2name[fname]
expr.name := rules.field2name |> get_value(fname)
var ev = expr.value ?as ExprVar
if ev == null
ev = (expr.value ?as ExprRef2Value) ?as ExprVar
Expand All @@ -146,30 +146,30 @@ class private TemplateVisitor : AstVisitor
def override visitExprAddr( var expr:smart_ptr<ExprAddr> ) : ExpressionPtr
let vn = string(expr.target)
if key_exists(rules.var2name,vn)
expr.target := rules.var2name[vn]
expr.target := rules.var2name |> get_value(vn)
return <- expr
def override visitExprLet( var expr:smart_ptr<ExprLet> ) : ExpressionPtr
for v in expr.variables
let vn = string(v.name)
if key_exists(rules.var2name,vn)
v.name := rules.var2name[vn]
v.name := rules.var2name |> get_value(vn)
return <- expr
def override visitExprVar(var expr:smart_ptr<ExprVar>) : ExpressionPtr
let vn = string(expr.name)
if key_exists(rules.var2name,vn)
expr.name := rules.var2name[vn]
expr.name := rules.var2name |> get_value(vn)
if key_exists(rules.var2expr,vn)
var inscope rexpr <- clone_expression(rules.var2expr[vn])
var inscope rexpr <- clone_expression(unsafe(rules.var2expr[vn]))
rexpr.at = expr.at
return <- rexpr
return <- expr
def replaceAlias ( var typ:TypeDeclPtr& )
if typ.baseType==Type alias
let ta = string(typ.alias)
if key_exists(rules.type2etype, ta)
move_new(typ) <| clone_type(rules.type2etype[ta])
move_new(typ) <| clone_type(unsafe(rules.type2etype[ta]))
elif key_exists(rules.type2type, ta)
typ.alias := rules.type2type[ta]
typ.alias := rules.type2type |> get_value(ta)
if typ.firstType != null
self->replaceAlias(typ.firstType)
if typ.secondType != null
Expand All @@ -184,14 +184,14 @@ class private TemplateVisitor : AstVisitor
for it in expr.iterators
let itn = string(it)
if key_exists(rules.var2name,itn)
it := rules.var2name[itn]
it := rules.var2name |> get_value(itn)
def override preVisitExprBlock(var blk:smart_ptr<ExprBlock>)
if !blk.blockFlags.isClosure
return
for arg in blk.arguments
let vn = "{arg.name}"
if key_exists(rules.blockArgName, vn)
arg.name := rules.blockArgName[vn]
arg.name := rules.blockArgName |> get_value(vn)
for ann in blk.annotations
rules.annArg |> get("{ann.annotation.name}") <| $(cb)
cb |> invoke(*ann)
Expand All @@ -214,7 +214,7 @@ class private TemplateVisitor : AstVisitor
for na in new_args
blk.arguments |> emplace(na, rai)
elif key_exists(rules.var2name, vname)
arg.name := rules.var2name[vname]
arg.name := rules.var2name |> get_value(vname)
def preVisitAnythingCall(var arguments:dasvector`smart_ptr`Expression) : void
if length(rules.var2exprList)==0
return
Expand All @@ -237,17 +237,17 @@ class private TemplateVisitor : AstVisitor
def override preVisitExprLooksLikeCall(var expr:smart_ptr<ExprLooksLikeCall>): void
let cname = string(expr.name)
if rules.call2name |> key_exists(cname)
expr.name := rules.call2name[cname]
expr.name := rules.call2name |> get_value(cname)
preVisitAnythingCall(expr.arguments)
def override preVisitExprCall(var expr:smart_ptr<ExprCall>): void
let cname = string(expr.name)
if rules.call2name |> key_exists(cname)
expr.name := rules.call2name[cname]
expr.name := rules.call2name |> get_value(cname)
preVisitAnythingCall(expr.arguments)
def override preVisitExprAddr(var expr:smart_ptr<ExprAddr>): void
let cname = string(expr.target)
if rules.call2name |> key_exists(cname)
expr.target := rules.call2name[cname]
expr.target := rules.call2name |> get_value(cname)
def override preVisitExprMakeArray(var expr:smart_ptr<ExprMakeArray>): void
preVisitAnythingCall(expr.values)

Expand Down
4 changes: 2 additions & 2 deletions examples/test/compilation_fail_tests/const_ref.das
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,8 @@ def test
if true
var a:table<string;int>
var b:table<string;int> const
a["key"]++
b["key"]++ // 30106: can't index in the constant table, use find instead
unsafe(a["key"])++
unsafe(b["key"])++ // 30106: can't index in the constant table, use find instead
if true
var a:int?
var b:int const?
Expand Down
19 changes: 10 additions & 9 deletions examples/test/optimizations/array_r2v.das
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,16 @@ struct Foo
x,y,z,w:int

def testA(var a)
for x in range(10)
a[x].y = x
a[3].z = 13
for x in range(10)
if x!=3
assert(a[x].x==0 && a[x].y==x && a[x].z==0 && a[x].w==0)
else
assert(a[x].x==0 && a[x].y==x && a[x].z==13 && a[x].w==0)
assert(a[3].z==13)
unsafe
for x in range(10)
a[x].y = x
a[3].z = 13
for x in range(10)
if x!=3
assert(a[x].x==0 && a[x].y==x && a[x].z==0 && a[x].w==0)
else
assert(a[x].x==0 && a[x].y==x && a[x].z==13 && a[x].w==0)
assert(a[3].z==13)

[export]
def test
Expand Down
6 changes: 3 additions & 3 deletions examples/test/unit_tests/clone.das
Original file line number Diff line number Diff line change
Expand Up @@ -62,13 +62,13 @@ def test_clone_array
def test_clone_table
var x, y : table<int;string>
for t in range(3)
x[t] = string(t)
x |> insert(t, string(t))
y := x
for t in range(3)
x[t] = string(t+1)
x |> insert(t, string(t+1))
assert(length(y)==3)
for t in range(3)
verify(y[t]==string(t))
verify(y |> get_value(t)==string(t))

[export]
def test
Expand Down
4 changes: 2 additions & 2 deletions examples/test/unit_tests/new_delete.das
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ def test_delete_array
def test_delete_table
var a : table<int;int>
let w0 = heap_bytes_allocated()
a[0] = 1
a[1] = 2
a |> insert(0,1)
a |> insert(1,2)
let w1 = heap_bytes_allocated()
delete a
let w2 = heap_bytes_allocated()
Expand Down
8 changes: 4 additions & 4 deletions examples/test/unit_tests/safe_index.das
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,9 @@ def test()
dummy = 0
ta?["one"] ?? dummy = 1
assert(dummy==1)
ta["one"] = 0
ta |> insert("one",0 )
ta?["one"] ?? dummy = 2
verify(length(ta)==1 && ta["one"]==2)
verify(length(ta)==1 && ta |> get_value("one")==2)
assert(dummy==1)

var pta = safe_addr(ta)
Expand All @@ -46,9 +46,9 @@ def test()
pta?["one"] ?? dummy = 1
assert(dummy==1)
assert(length(ta)==0)
ta["one"] = 1
ta |> insert("one",1)
pta?["one"] ?? dummy = 2
verify(length(ta)==1 && ta["one"]==2)
verify(length(ta)==1 && ta |> get_value("one")==2)
assert(dummy==1)
pta = null
pta?["one"] ?? dummy = 3
Expand Down
Loading

0 comments on commit da3d78f

Please sign in to comment.