#include "AST.h" #include "types.h" #include "buildexpr.h" extern const string int2string(int); static map_cstring_to_int *memo = NULL; /* The next two variables are related to naming the introduced variables. */ static int buildexprCount; static int buildexprPrefix = 0; void reset_buildexpr() { delete memo; memo = new map_cstring_to_int; buildexprCount = 0; buildexprPrefix++; } static const string name(int i) { return "b" + int2string(buildexprPrefix) + '_' + int2string(i); } const string build(const string expr, const CtType &t, CodeContext &context) { int &result = (*memo)[expr]; if (result == 0) { result = ++buildexprCount; context.declare(name(result), t); context << name(result) << " = " << expr << ';' << endCline; } return name(result); } static const string buildInfix(const string &a, const string &op, const string &b, const CtType &t, CodeContext &context) { return build("(" + a + " " + op + " " + b + ")", t, context); } static const string buildPrefix(const string &op, const string &a, const CtType &t, CodeContext &context) { return build("(" + op + " " + a + ")", t, context); } const string product(const string &a, const string &b, CodeContext &context) { return product(a, b, theIntType->cType(), context); } const string quotient(const string &a, const string &b, CodeContext &context) { return quotient(a, b, theIntType->cType(), context); } const string quotient_with_check(const string &a, const string &b, const string &y, CodeContext &context) { return quotient_with_check(a, b, y, theIntType->cType(), context); } const string quotient_with_runtime_unitdivisor_opt(const string &a, const string &b, CodeContext &context) { if (a == "0" || b == "1") return a; else { string s = build(b, theIntType->cType(), context); return build("(" + s + " == 1 ? " + a + " : (" + a + " / " + s + "))", theIntType->cType(), context); } } const string sum(const string &a, const string &b, CodeContext &context) { return sum(a, b, theIntType->cType(), context); } const string min(llist *l, CodeContext &context) { return min(l, theIntType->cType(), context); } const string difference(const string &a, const string &b, CodeContext &context) { return difference(a, b, theIntType->cType(), context); } const string neg(const string &a, CodeContext &context) { return neg(a, theIntType->cType(), context); } ///////////////////////////////////////////////////////////////////////////// const string product(const string &a, const string &b, const CtType &t, CodeContext &context) { if (a == "0" || b == "0") return "0"; if (a == "1") return b; if (b == "1") return a; return buildInfix(a, string("*"), b, t, context); } const string quotient(const string &a, const string &b, const CtType &t, CodeContext &context) { return (a == "0" || b == "1") ? a : buildInfix(a, string("/"), b, t, context); } const string quotient_with_check(const string &a, const string &b, const string &y, const CtType &t, CodeContext &context) { if (a == "0" || b == "1") return a; string q = buildInfix(a, string("/"), b, t, context); if (y != "0") context << "BOUNDS_CHECK((!" << y << " || " "(" << q << " * " << b << ") == " << a << "), " "\"array access out of bounds (usually a stride problem)\");" << endCline; return q; } const string sum(const string &a, const string &b, const CtType &t, CodeContext &context) { return (a == "0") ? b : (b == "0" ? a : buildInfix(a, string("+"), b, t, context)); } const string min(llist *l, const CtType &t, CodeContext &context) { int n = l->size(); assert(n > 0); if (n == 1) return l->front(); else { llist *r = NULL; while (true) { const string a = l->front(), b = l->tail()->front(); r = cons(build("((" + a + " < " + b + ") ? " + a + " : " + b + ")", t, context), r); l = l->tail()->tail(); if (l == NULL) return min(r, t, context); else if (l->tail() == NULL) return min(cons(l->front(), r), t, context); } } } const string difference(const string &a, const string &b, const CtType &t, CodeContext &context) { return sum(a, neg(b, t, context), t, context); } const string neg(const string &a, const CtType &t, CodeContext &context) { return (a == "0") ? a : buildPrefix(string("-"), a, t, context); }