aboutsummaryrefslogtreecommitdiffstats
path: root/Godeps/_workspace/src/github.com/ethereum/serpent-go/serpent/rewriteutils.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Godeps/_workspace/src/github.com/ethereum/serpent-go/serpent/rewriteutils.cpp')
-rw-r--r--Godeps/_workspace/src/github.com/ethereum/serpent-go/serpent/rewriteutils.cpp211
1 files changed, 211 insertions, 0 deletions
diff --git a/Godeps/_workspace/src/github.com/ethereum/serpent-go/serpent/rewriteutils.cpp b/Godeps/_workspace/src/github.com/ethereum/serpent-go/serpent/rewriteutils.cpp
new file mode 100644
index 000000000..0d810bdbc
--- /dev/null
+++ b/Godeps/_workspace/src/github.com/ethereum/serpent-go/serpent/rewriteutils.cpp
@@ -0,0 +1,211 @@
+#include <stdio.h>
+#include <iostream>
+#include <vector>
+#include <map>
+#include "util.h"
+#include "lllparser.h"
+#include "bignum.h"
+#include "rewriteutils.h"
+#include "optimize.h"
+
+// Valid functions and their min and max argument counts
+std::string validFunctions[][3] = {
+ { "if", "2", "3" },
+ { "unless", "2", "2" },
+ { "while", "2", "2" },
+ { "until", "2", "2" },
+ { "alloc", "1", "1" },
+ { "array", "1", "1" },
+ { "call", "2", tt256 },
+ { "callcode", "2", tt256 },
+ { "create", "1", "4" },
+ { "getch", "2", "2" },
+ { "setch", "3", "3" },
+ { "sha3", "1", "2" },
+ { "return", "1", "2" },
+ { "inset", "1", "1" },
+ { "min", "2", "2" },
+ { "max", "2", "2" },
+ { "array_lit", "0", tt256 },
+ { "seq", "0", tt256 },
+ { "log", "1", "6" },
+ { "outer", "1", "1" },
+ { "set", "2", "2" },
+ { "get", "1", "1" },
+ { "ref", "1", "1" },
+ { "declare", "1", tt256 },
+ { "with", "3", "3" },
+ { "outer", "1", "1" },
+ { "mcopy", "3", "3" },
+ { "unsafe_mcopy", "3", "3" },
+ { "save", "3", "3" },
+ { "load", "2", "2" },
+ { "---END---", "", "" } //Keep this line at the end of the list
+};
+
+std::map<std::string, bool> vfMap;
+
+// Is a function name one of the valid functions above?
+bool isValidFunctionName(std::string f) {
+ if (vfMap.size() == 0) {
+ for (int i = 0; ; i++) {
+ if (validFunctions[i][0] == "---END---") break;
+ vfMap[validFunctions[i][0]] = true;
+ }
+ }
+ return vfMap.count(f);
+}
+
+// Cool function for debug purposes (named cerrStringList to make
+// all prints searchable via 'cerr')
+void cerrStringList(std::vector<std::string> s, std::string suffix) {
+ for (unsigned i = 0; i < s.size(); i++) std::cerr << s[i] << " ";
+ std::cerr << suffix << "\n";
+}
+
+// Convert:
+// self.cow -> ["cow"]
+// self.horse[0] -> ["horse", "0"]
+// self.a[6][7][self.storage[3]].chicken[9] ->
+// ["6", "7", (sload 3), "chicken", "9"]
+std::vector<Node> listfyStorageAccess(Node node) {
+ std::vector<Node> out;
+ std::vector<Node> nodez;
+ nodez.push_back(node);
+ while (1) {
+ if (nodez.back().type == TOKEN) {
+ out.push_back(token("--" + nodez.back().val, node.metadata));
+ std::vector<Node> outrev;
+ for (int i = (signed)out.size() - 1; i >= 0; i--) {
+ outrev.push_back(out[i]);
+ }
+ return outrev;
+ }
+ if (nodez.back().val == ".")
+ nodez.back().args[1].val = "--" + nodez.back().args[1].val;
+ if (nodez.back().args.size() == 0)
+ err("Error parsing storage variable statement", node.metadata);
+ if (nodez.back().args.size() == 1)
+ out.push_back(token(tt256m1, node.metadata));
+ else
+ out.push_back(nodez.back().args[1]);
+ nodez.push_back(nodez.back().args[0]);
+ }
+}
+
+// Is the given node something of the form
+// self.cow
+// self.horse[0]
+// self.a[6][7][self.storage[3]].chicken[9]
+bool isNodeStorageVariable(Node node) {
+ std::vector<Node> nodez;
+ nodez.push_back(node);
+ while (1) {
+ if (nodez.back().type == TOKEN) return false;
+ if (nodez.back().args.size() == 0) return false;
+ if (nodez.back().val != "." && nodez.back().val != "access")
+ return false;
+ if (nodez.back().args[0].val == "self") return true;
+ nodez.push_back(nodez.back().args[0]);
+ }
+}
+
+// Main pattern matching routine, for those patterns that can be expressed
+// using our standard mini-language above
+//
+// Returns two values. First, a boolean to determine whether the node matches
+// the pattern, second, if the node does match then a map mapping variables
+// in the pattern to nodes
+matchResult match(Node p, Node n) {
+ matchResult o;
+ o.success = false;
+ if (p.type == TOKEN) {
+ if (p.val == n.val && n.type == TOKEN) o.success = true;
+ else if (p.val[0] == '$' || p.val[0] == '@') {
+ o.success = true;
+ o.map[p.val.substr(1)] = n;
+ }
+ }
+ else if (n.type==TOKEN || p.val!=n.val || p.args.size()!=n.args.size()) {
+ // do nothing
+ }
+ else {
+ for (unsigned i = 0; i < p.args.size(); i++) {
+ matchResult oPrime = match(p.args[i], n.args[i]);
+ if (!oPrime.success) {
+ o.success = false;
+ return o;
+ }
+ for (std::map<std::string, Node>::iterator it = oPrime.map.begin();
+ it != oPrime.map.end();
+ it++) {
+ o.map[(*it).first] = (*it).second;
+ }
+ }
+ o.success = true;
+ }
+ return o;
+}
+
+
+// Fills in the pattern with a dictionary mapping variable names to
+// nodes (these dicts are generated by match). Match and subst together
+// create a full pattern-matching engine.
+Node subst(Node pattern,
+ std::map<std::string, Node> dict,
+ std::string varflag,
+ Metadata m) {
+ // Swap out patterns at the token level
+ if (pattern.metadata.ln == -1)
+ pattern.metadata = m;
+ if (pattern.type == TOKEN &&
+ pattern.val[0] == '$') {
+ if (dict.count(pattern.val.substr(1))) {
+ return dict[pattern.val.substr(1)];
+ }
+ else {
+ return token(varflag + pattern.val.substr(1), m);
+ }
+ }
+ // Other tokens are untouched
+ else if (pattern.type == TOKEN) {
+ return pattern;
+ }
+ // Substitute recursively for ASTs
+ else {
+ std::vector<Node> args;
+ for (unsigned i = 0; i < pattern.args.size(); i++) {
+ args.push_back(subst(pattern.args[i], dict, varflag, m));
+ }
+ return asn(pattern.val, args, m);
+ }
+}
+
+// Transforms a sequence containing two-argument with statements
+// into a statement containing those statements in nested form
+Node withTransform (Node source) {
+ Node o = token("--");
+ Metadata m = source.metadata;
+ std::vector<Node> args;
+ for (int i = source.args.size() - 1; i >= 0; i--) {
+ Node a = source.args[i];
+ if (a.val == "with" && a.args.size() == 2) {
+ std::vector<Node> flipargs;
+ for (int j = args.size() - 1; j >= 0; j--)
+ flipargs.push_back(args[i]);
+ if (o.val != "--")
+ flipargs.push_back(o);
+ o = asn("with", a.args[0], a.args[1], asn("seq", flipargs, m), m);
+ args = std::vector<Node>();
+ }
+ else {
+ args.push_back(a);
+ }
+ }
+ std::vector<Node> flipargs;
+ for (int j = args.size() - 1; j >= 0; j--)
+ flipargs.push_back(args[j]);
+ if (o.val != "--")
+ flipargs.push_back(o);
+ return asn("seq", flipargs, m);
+}