-
Notifications
You must be signed in to change notification settings - Fork 16
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
e390c70
commit 7f2e646
Showing
7 changed files
with
204 additions
and
7 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
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,4 +5,4 @@ cases: | |
- name: WriteAndRead | ||
outputs: | ||
sum: "2,4,6,8," | ||
o: "table> is at line: 2" | ||
o: "table> is at line: 3" |
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 |
---|---|---|
@@ -1,4 +1,4 @@ | ||
:timeok=time() | ||
:timeok=time()==2 | ||
:absok=abs(-5)==ABS(5) | ||
if abs(-2)==abs(2) then | ||
:absinfiok=1 | ||
|
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 |
---|---|---|
|
@@ -4,4 +4,4 @@ cases: | |
- name: TestOutputstring | ||
outputs: | ||
out: "abcdef" | ||
text: "d is at line: 4" | ||
text: "d is at line: 5" |
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 |
---|---|---|
|
@@ -3,4 +3,4 @@ scripts: | |
cases: | ||
- name: TestRenaming | ||
outputs: | ||
out: "hallo welt123 2" | ||
out: "hallo welt123 4" |
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,181 @@ | ||
package nolol | ||
|
||
import ( | ||
"fmt" | ||
"sort" | ||
"strings" | ||
|
||
"github.com/dbaumgarten/yodk/pkg/nolol/nast" | ||
"github.com/dbaumgarten/yodk/pkg/parser/ast" | ||
) | ||
|
||
type constant struct { | ||
Expression ast.Expression | ||
Replacement string | ||
} | ||
|
||
func (c *Converter) globalizeConstants(prog *nast.Program) error { | ||
|
||
counter := 0 | ||
templ := "_const%d" | ||
|
||
numberConstants := make(map[string]constant) | ||
stringConstants := make(map[string]constant) | ||
|
||
store := func(value string, exp ast.Expression, set map[string]constant) *ast.Dereference { | ||
old, exists := set[value] | ||
if exists { | ||
return &ast.Dereference{ | ||
Position: exp.Start(), | ||
Variable: old.Replacement, | ||
} | ||
} | ||
c := constant{ | ||
Expression: exp, | ||
Replacement: fmt.Sprintf(templ, counter), | ||
} | ||
set[value] = c | ||
counter++ | ||
return &ast.Dereference{ | ||
Position: exp.Start(), | ||
Variable: c.Replacement, | ||
} | ||
} | ||
|
||
findConstants := func(node ast.Node, visitType int) error { | ||
if visitType == ast.PostVisit || visitType == ast.SingleVisit { | ||
numConst, isNumber := node.(*ast.NumberConstant) | ||
stringConst, isString := node.(*ast.StringConstant) | ||
|
||
if isNumber && len(numConst.Value) > 1 { | ||
repl := store(numConst.Value, numConst, numberConstants) | ||
return ast.NewNodeReplacementSkip(repl) | ||
} else if isString { | ||
repl := store(stringConst.Value, stringConst, stringConstants) | ||
return ast.NewNodeReplacementSkip(repl) | ||
} | ||
|
||
} | ||
return nil | ||
} | ||
|
||
err := prog.Accept(ast.VisitorFunc(findConstants)) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
constantlist := make([]constant, 0, len(stringConstants)+len(numberConstants)) | ||
for _, con := range stringConstants { | ||
constantlist = append(constantlist, con) | ||
} | ||
for _, con := range numberConstants { | ||
constantlist = append(constantlist, con) | ||
} | ||
|
||
sortConstantList(constantlist) | ||
|
||
// find variables that are assigned ONLY ONCE and with an globalized constant | ||
// These assignments are removed and all future dereferences are replaced with the globalized constant | ||
constantAliases := make(map[string]string) | ||
nonConstantAliases := make(map[string]bool) | ||
|
||
findConstantAliases := func(node ast.Node, visitType int) error { | ||
if ass, is := node.(*ast.Assignment); is && visitType == ast.PreVisit { | ||
|
||
// Ignore it if there is more than one assignment | ||
if _, alreadyExists := constantAliases[strings.ToLower(ass.Variable)]; alreadyExists { | ||
nonConstantAliases[strings.ToLower(ass.Variable)] = true | ||
} | ||
|
||
if val, is := ass.Value.(*ast.Dereference); is { | ||
// only when the value is a variable starting with __const and the variable is not a global | ||
if strings.HasPrefix(val.Variable, "_const") && !strings.HasPrefix(ass.Variable, ":") { | ||
constantAliases[strings.ToLower(ass.Variable)] = val.Variable | ||
} | ||
} | ||
} | ||
|
||
// ignore variables that are dereferenced with a modifying operator | ||
if deref, is := node.(*ast.Dereference); is && visitType == ast.SingleVisit { | ||
if deref.Operator != "" { | ||
nonConstantAliases[strings.ToLower(deref.Variable)] = true | ||
} | ||
} | ||
return nil | ||
} | ||
|
||
err = prog.Accept(ast.VisitorFunc(findConstantAliases)) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
// remove the variables that are determined as non-candidates from our list | ||
for k := range nonConstantAliases { | ||
delete(constantAliases, k) | ||
} | ||
|
||
replaceConstantAliases := func(node ast.Node, visitType int) error { | ||
if ass, is := node.(*ast.Assignment); is && visitType == ast.PreVisit { | ||
if _, exists := constantAliases[strings.ToLower(ass.Variable)]; exists { | ||
return ast.NewNodeReplacement() | ||
} | ||
} | ||
if deref, is := node.(*ast.Dereference); is && visitType == ast.SingleVisit { | ||
alias, exists := constantAliases[strings.ToLower(deref.Variable)] | ||
if exists { | ||
deref.Variable = alias | ||
} | ||
} | ||
return nil | ||
} | ||
|
||
err = prog.Accept(ast.VisitorFunc(replaceConstantAliases)) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
// Add the globalized constants and wrap the original code in a while loop | ||
|
||
lines := make([]nast.Element, 0, len(constantlist)+1) | ||
for _, con := range constantlist { | ||
lines = append(lines, &nast.StatementLine{ | ||
Line: ast.Line{ | ||
Position: ast.UnknownPosition, | ||
Statements: []ast.Statement{ | ||
&ast.Assignment{ | ||
Position: ast.UnknownPosition, | ||
Variable: con.Replacement, | ||
Operator: "=", | ||
Value: con.Expression, | ||
}, | ||
}, | ||
}, | ||
}) | ||
} | ||
|
||
loop := &nast.WhileLoop{ | ||
Position: ast.UnknownPosition, | ||
Condition: &ast.NumberConstant{ | ||
Value: "1", | ||
}, | ||
Block: &nast.Block{ | ||
Elements: make([]nast.NestableElement, 0, len(prog.Elements)), | ||
}, | ||
} | ||
for _, el := range prog.Elements { | ||
loop.Block.Elements = append(loop.Block.Elements, el.(nast.NestableElement)) | ||
} | ||
|
||
lines = append(lines, loop) | ||
|
||
prog.Elements = lines | ||
return nil | ||
} | ||
|
||
func sortConstantList(li []constant) { | ||
sort.Slice(li, func(i, j int) bool { | ||
one := li[i] | ||
two := li[j] | ||
return one.Replacement > two.Replacement | ||
}) | ||
} |
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