-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
breaking swaps out into their own thing.
- Loading branch information
Showing
9 changed files
with
285 additions
and
31 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
spec swaps; | ||
|
||
def s1 = stock{ | ||
v: 10, | ||
}; | ||
|
||
def f1 = flow{ | ||
target: new s1, | ||
fn: func{ | ||
target.v <- 2; | ||
}, | ||
}; | ||
|
||
for 2 run { | ||
f2 = new f1; | ||
s2 = new s1; | ||
f2.target = s2; | ||
s2.v = 20; | ||
f2.fn; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
(set-logic QF_NRA)(declare-fun swaps_s2_v_0 () Real) | ||
(declare-fun swaps_f2_target_v_0 () Real) | ||
(declare-fun swaps_f2_target_v_1 () Real) | ||
(declare-fun swaps_f2_target_v_2 () Real) | ||
(assert (= swaps_s2_v_0 20.0)) | ||
(assert (= swaps_f2_target_v_0 20.0)) | ||
(assert (= swaps_f2_target_v_1 (+ swaps_f2_target_v_0 2.0))) | ||
(assert (= swaps_f2_target_v_2 (+ swaps_f2_target_v_1 2.0))) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,191 @@ | ||
package swaps | ||
|
||
import ( | ||
"fault/ast" | ||
"fault/types" | ||
"fault/util" | ||
"fmt" | ||
|
||
"github.com/barkimedes/go-deepcopy" | ||
) | ||
|
||
type Precompiler struct { | ||
checker *types.Checker | ||
} | ||
|
||
func NewPrecompiler(check *types.Checker) *Precompiler { | ||
return &Precompiler{ | ||
checker: check, | ||
} | ||
} | ||
|
||
func (c *Precompiler) Swap(n *ast.Spec) *ast.Spec { | ||
s := c.walk(n) | ||
return s.(*ast.Spec) | ||
} | ||
|
||
func (c *Precompiler) walk(n ast.Node) ast.Node { | ||
var err error | ||
switch node := n.(type) { | ||
case *ast.StructInstance: | ||
node, err = c.swapValues(node) | ||
if err != nil { | ||
panic(err) | ||
} | ||
return node | ||
case *ast.Spec: | ||
var st []ast.Statement | ||
for _, v := range node.Statements { | ||
snode := c.walk(v) | ||
st = append(st, snode.(ast.Statement)) | ||
} | ||
node.Statements = st | ||
return node | ||
case *ast.SpecDeclStatement: | ||
return node | ||
case *ast.SysDeclStatement: | ||
return node | ||
case *ast.ImportStatement: | ||
snode := c.walk(node.Tree) | ||
node.Tree = snode.(*ast.Spec) | ||
return node | ||
case *ast.ConstantStatement: | ||
return node | ||
case *ast.Identifier: | ||
return node | ||
case *ast.DefStatement: | ||
return node | ||
case *ast.StockLiteral: | ||
return node | ||
case *ast.FlowLiteral: | ||
return node | ||
case *ast.ComponentLiteral: | ||
return node | ||
case *ast.AssertionStatement: | ||
return node | ||
case *ast.ForStatement: | ||
var st []ast.Statement | ||
for _, v := range node.Body.Statements { | ||
snode := c.walk(v) | ||
st = append(st, snode.(ast.Statement)) | ||
} | ||
node.Body.Statements = st | ||
return node | ||
case *ast.StartStatement: | ||
return node | ||
case *ast.FunctionLiteral: | ||
return node | ||
case *ast.BlockStatement: | ||
if node == nil { | ||
return node | ||
} | ||
for i := 0; i < len(node.Statements); i++ { | ||
if e, ok := node.Statements[i].(*ast.ExpressionStatement); ok { | ||
snode := c.walk(e.Expression) | ||
node.Statements[i].(*ast.ExpressionStatement).Expression = snode.(ast.Expression) | ||
} | ||
} | ||
return node | ||
case *ast.BuiltIn: | ||
return node | ||
case *ast.IntegerLiteral: | ||
return node | ||
case *ast.FloatLiteral: | ||
return node | ||
case *ast.Boolean: | ||
return node | ||
case *ast.StringLiteral: | ||
return node | ||
case *ast.ParameterCall: | ||
return node | ||
case *ast.ExpressionStatement: | ||
snode := c.walk(node.Expression) | ||
node.Expression = snode.(ast.Expression) | ||
return node | ||
case *ast.Natural: | ||
return node | ||
case *ast.Uncertain: | ||
return node | ||
case *ast.Unknown: | ||
return node | ||
case *ast.PrefixExpression: | ||
return node | ||
case *ast.InfixExpression: | ||
return node | ||
case *ast.This: | ||
return node | ||
case *ast.Clock: | ||
return node | ||
case *ast.Nil: | ||
return node | ||
case *ast.ParallelFunctions: | ||
return node | ||
case *ast.InitExpression: | ||
return node | ||
case *ast.IfExpression: | ||
if node == nil { | ||
return node | ||
} | ||
//Not sure to allow this | ||
con := c.walk(node.Consequence) | ||
alt := c.walk(node.Alternative) | ||
elif := c.walk(node.Elif) | ||
node.Consequence = con.(*ast.BlockStatement) | ||
node.Alternative = alt.(*ast.BlockStatement) | ||
node.Elif = elif.(*ast.IfExpression) | ||
return node | ||
case *ast.IndexExpression: | ||
return node | ||
case *ast.InvariantClause: | ||
return node | ||
default: | ||
panic(fmt.Errorf("unimplemented: %s type %T", node, node)) | ||
} | ||
} | ||
|
||
func (c *Precompiler) swapValues(base *ast.StructInstance) (*ast.StructInstance, error) { | ||
for _, s := range base.Swaps { | ||
infix := s.(*ast.InfixExpression) | ||
rawid := infix.Left.(ast.Nameable).RawId() | ||
key := rawid[len(rawid)-1] | ||
val, err := c.checker.Reference(infix.Right) | ||
if err != nil { | ||
return base, err | ||
} | ||
|
||
// Because part of what we're doing here is renaming | ||
// these nodes. We need to do a deep copy to separate | ||
// the swapped nodes from their original reference values | ||
copyVal, err := deepcopy.Anything(val) | ||
if err != nil { | ||
return base, err | ||
} | ||
|
||
val = copyVal.(ast.Node) | ||
|
||
switch v := val.(type) { | ||
case *ast.StructInstance: | ||
v.Name = key | ||
val = v | ||
} | ||
|
||
base.Properties[key].Value = val | ||
base = c.swapDeepNames(base) | ||
|
||
} | ||
return base, nil | ||
} | ||
|
||
func (c *Precompiler) swapDeepNames(val *ast.StructInstance) *ast.StructInstance { | ||
rawid := val.RawId() | ||
err := c.checker.SpecStructs[rawid[0]].Update(rawid, util.ExtractBranches(val.Properties)) | ||
if err != nil { | ||
panic(fmt.Sprintf("failed to update spec record on swap %s: %s", val.String(), err)) | ||
} | ||
|
||
node, err := c.checker.Preprocesser.Partial(rawid[0], val) | ||
if err != nil { | ||
panic(fmt.Sprintf("failed to update process ids on swap %s: %s", val.String(), err)) | ||
} | ||
return node.(*ast.StructInstance) | ||
} |
Oops, something went wrong.