summaryrefslogtreecommitdiff
path: root/src/emscripten-optimizer/simple_ast.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/emscripten-optimizer/simple_ast.h')
-rw-r--r--src/emscripten-optimizer/simple_ast.h164
1 files changed, 48 insertions, 116 deletions
diff --git a/src/emscripten-optimizer/simple_ast.h b/src/emscripten-optimizer/simple_ast.h
index f4dce76aa..784f49632 100644
--- a/src/emscripten-optimizer/simple_ast.h
+++ b/src/emscripten-optimizer/simple_ast.h
@@ -44,8 +44,8 @@
namespace cashew {
-struct Ref;
struct Value;
+struct Ref;
void dump(const char *str, Ref node, bool pretty=false);
@@ -96,6 +96,8 @@ public:
}
};
+struct Assign;
+
// Main value type
struct Value {
enum Type {
@@ -104,7 +106,8 @@ struct Value {
Array = 2,
Null = 3,
Bool = 4,
- Object = 5
+ Object = 5,
+ Assign_ = 6 // ref = target
};
Type type;
@@ -122,6 +125,7 @@ struct Value {
ArrayStorage *arr;
bool boo;
ObjectStorage *obj;
+ Ref ref;
};
// constructors all copy their input
@@ -198,13 +202,15 @@ struct Value {
obj = new ObjectStorage();
return *this;
}
+ Value& setAssign(Ref target, Ref value);
bool isString() { return type == String; }
bool isNumber() { return type == Number; }
bool isArray() { return type == Array; }
bool isNull() { return type == Null; }
bool isBool() { return type == Bool; }
- bool isObject() { return type == Object; }
+ bool isObject() { return type == Object; }
+ bool isAssign() { return type == Assign_; }
bool isBool(bool b) { return type == Bool && b == boo; } // avoid overloading == as it might overload over int
@@ -237,6 +243,8 @@ struct Value {
return boo;
}
+ Assign* asAssign();
+
int32_t getInteger() { // convenience function to get a known integer
assert(fmod(getNumber(), 1) == 0);
int32_t ret = getNumber();
@@ -262,7 +270,7 @@ struct Value {
case Bool:
setBool(other.boo);
break;
- case Object:
+ default:
abort(); // TODO
}
return *this;
@@ -283,31 +291,12 @@ struct Value {
return boo == other.boo;
case Object:
return this == &other; // if you want a deep compare, use deepCompare
+ default:
+ abort();
}
return true;
}
- bool deepCompare(Ref ref) {
- Value& other = *ref;
- if (*this == other) return true; // either same pointer, or identical value type (string, number, null or bool)
- if (type != other.type) return false;
- if (type == Array) {
- if (arr->size() != other.arr->size()) return false;
- for (unsigned i = 0; i < arr->size(); i++) {
- if (!(*arr)[i]->deepCompare((*other.arr)[i])) return false;
- }
- return true;
- } else if (type == Object) {
- if (obj->size() != other.obj->size()) return false;
- for (auto i : *obj) {
- if (other.obj->count(i.first) == 0) return false;
- if (i.second->deepCompare((*other.obj)[i.first])) return false;
- }
- return true;
- }
- return false;
- }
-
char* parse(char* curr) {
#define is_json_space(x) (x == 32 || x == 9 || x == 10 || x == 13) /* space, tab, linefeed/newline, or return */
#define skip() { while (*curr && is_json_space(*curr)) curr++; }
@@ -387,78 +376,7 @@ struct Value {
return curr;
}
- void stringify(std::ostream &os, bool pretty=false) {
- static int indent = 0;
- #define indentify() { for (int i_ = 0; i_ < indent; i_++) os << " "; }
- switch (type) {
- case String:
- if (str.str) {
- os << '"' << str.str << '"';
- } else {
- os << "\"(null)\"";
- }
- break;
- case Number:
- os << std::setprecision(17) << num; // doubles can have 17 digits of precision
- break;
- case Array:
- if (arr->size() == 0) {
- os << "[]";
- break;
- }
- os << '[';
- if (pretty) {
- os << std::endl;
- indent++;
- }
- for (size_t i = 0; i < arr->size(); i++) {
- if (i > 0) {
- if (pretty) os << "," << std::endl;
- else os << ", ";
- }
- indentify();
- (*arr)[i]->stringify(os, pretty);
- }
- if (pretty) {
- os << std::endl;
- indent--;
- }
- indentify();
- os << ']';
- break;
- case Null:
- os << "null";
- break;
- case Bool:
- os << (boo ? "true" : "false");
- break;
- case Object:
- os << '{';
- if (pretty) {
- os << std::endl;
- indent++;
- }
- bool first = true;
- for (auto i : *obj) {
- if (first) {
- first = false;
- } else {
- os << ", ";
- if (pretty) os << std::endl;
- }
- indentify();
- os << '"' << i.first.c_str() << "\": ";
- i.second->stringify(os, pretty);
- }
- if (pretty) {
- os << std::endl;
- indent--;
- }
- indentify();
- os << '}';
- break;
- }
- }
+ void stringify(std::ostream &os, bool pretty=false);
// String operations
@@ -559,6 +477,25 @@ struct Value {
}
};
+struct Assign : public Value {
+ Ref value_;
+
+ Assign(Ref targetInit, Ref valueInit) {
+ type = Assign_;
+ target() = targetInit;
+ value() = valueInit;
+ }
+
+ Assign() : Assign(nullptr, nullptr) {}
+
+ Ref& target() {
+ return ref;
+ }
+ Ref& value() {
+ return value_;
+ }
+};
+
// AST traversals
// Traverse, calling visit before the children
@@ -663,12 +600,14 @@ struct JSPrinter {
printNum(node);
return;
}
+ if (node->isAssign()) {
+ printAssign(node);
+ }
IString type = node[0]->getIString();
//fprintf(stderr, "printing %s\n", type.str);
switch (type.str[0]) {
case 'a': {
- if (type == ASSIGN) printAssign(node);
- else if (type == ARRAY) printArray(node);
+ if (type == ARRAY) printArray(node);
else abort();
break;
}
@@ -829,11 +768,12 @@ struct JSPrinter {
}
void printAssign(Ref node) {
- printChild(node[2], node, -1);
+ auto* assign = node->asAssign();
+ printChild(assign->target(), node, -1);
space();
emit('=');
space();
- printChild(node[3], node, 1);
+ printChild(assign->value(), node, 1);
}
void printName(Ref node) {
@@ -980,6 +920,9 @@ struct JSPrinter {
}
int getPrecedence(Ref node, bool parent) {
+ if (node->isAssign()) {
+ return OperatorClass::getPrecedence(OperatorClass::Binary, SET);
+ }
Ref type = node[0];
if (type == BINARY || type == UNARY_PREFIX) {
return OperatorClass::getPrecedence(type == BINARY ? OperatorClass::Binary : OperatorClass::Prefix, node[1]->getIString());
@@ -987,8 +930,6 @@ struct JSPrinter {
return OperatorClass::getPrecedence(OperatorClass::Binary, COMMA);
} else if (type == CALL) {
return parent ? OperatorClass::getPrecedence(OperatorClass::Binary, COMMA) : -1; // call arguments are split by commas, but call itself is safe
- } else if (type == ASSIGN) {
- return OperatorClass::getPrecedence(OperatorClass::Binary, SET);
} else if (type == CONDITIONAL) {
return OperatorClass::getPrecedence(OperatorClass::Tertiary, QUESTION);
}
@@ -1454,7 +1395,7 @@ public:
}
static Ref makeStatement(Ref contents) {
- if (contents->isNumber() || contents->isString() || statable.has(contents[0]->getIString())) {
+ if (contents->isNumber() || contents->isString() || contents->isAssign() || statable.has(contents[0]->getIString())) {
return &makeRawArray(2)->push_back(makeRawString(STAT))
.push_back(contents);
} else {
@@ -1480,10 +1421,7 @@ public:
static Ref makeBinary(Ref left, IString op, Ref right) {
if (op == SET) {
- return &makeRawArray(4)->push_back(makeRawString(ASSIGN))
- .push_back(&arena.alloc<Value>()->setBool(true))
- .push_back(left)
- .push_back(right);
+ return &arena.alloc<Assign>()->setAssign(left, right);
} else if (op == COMMA) {
return &makeRawArray(3)->push_back(makeRawString(SEQ))
.push_back(left)
@@ -1661,16 +1599,10 @@ public:
}
static Ref makeAssign(Ref target, Ref value) {
- return &makeRawArray(3)->push_back(makeRawString(ASSIGN))
- .push_back(&arena.alloc<Value>()->setBool(true))
- .push_back(target)
- .push_back(value);
+ return &arena.alloc<Assign>()->setAssign(target, value);
}
static Ref makeAssign(IString target, Ref value) {
- return &makeRawArray(3)->push_back(makeRawString(ASSIGN))
- .push_back(&arena.alloc<Value>()->setBool(true))
- .push_back(makeName(target))
- .push_back(value);
+ return &arena.alloc<Assign>()->setAssign(makeName(target), value);
}
static Ref makeSub(Ref obj, Ref index) {