#include "nodes.hpp" #include "std.hpp" #include #include ////////////////////////////////// // Cast an expression to a type // ////////////////////////////////// ExprNode* ExprNode::castTo(Type* ty, Environ* e) { if (!sem_type->canCastTo(ty)) { ex("Illegal type conversion"); } ExprNode* cast = new CastNode(this, ty); cast->semant(e); return cast; } ExprNode* CastNode::semant(Environ* e) { if (!expr->sem_type) { expr = expr->semant(e); } if (ConstNode* c = expr->constNode()) { ExprNode* e; if (type == Type::int_type) e = new IntConstNode(c->intValue()); else if (type == Type::float_type) e = new FloatConstNode(c->floatValue()); else e = new StringConstNode(c->stringValue()); delete this; return e; } sem_type = type; return this; } ////////////////////////////////// // Cast an expression to a type // ////////////////////////////////// TNode* CastNode::translate(Codegen* g) { TNode* t = expr->translate(g); if (expr->sem_type == Type::float_type && sem_type == Type::int_type) { //float->int return new TNode(IR_CAST, t, 0); } if (expr->sem_type == Type::int_type && sem_type == Type::float_type) { //int->float return new TNode(IR_FCAST, t, 0); } if (expr->sem_type == Type::string_type && sem_type == Type::int_type) { //str->int return call("__bbStrToInt", t); } if (expr->sem_type == Type::int_type && sem_type == Type::string_type) { //int->str return call("__bbStrFromInt", t); } if (expr->sem_type == Type::string_type && sem_type == Type::float_type) { //str->float return fcall("__bbStrToFloat", t); } if (expr->sem_type == Type::float_type && sem_type == Type::string_type) { //float->str return call("__bbStrFromFloat", t); } if (expr->sem_type->structType() && sem_type == Type::string_type) { //obj->str return call("__bbObjToStr", t); } return t; } ///////////////////////////// // Sequence of Expressions // ///////////////////////////// void ExprSeqNode::semant(Environ* e) { for (int k = 0; k < exprs.size(); ++k) { if (exprs[k]) exprs[k] = exprs[k]->semant(e); } } TNode* ExprSeqNode::translate(Codegen* g, bool cfunc) { TNode *t = 0, *l = 0; for (int k = 0; k < exprs.size(); ++k) { TNode* q = exprs[k]->translate(g); if (cfunc) { Type* ty = exprs[k]->sem_type; if (ty->stringType()) { q = call("__bbStrToCStr", q); } else if (ty->structType()) { q = new TNode(IR_MEM, q); } else if (ty == Type::void_type) { q = new TNode(IR_MEM, add(q, iconst(4))); } } TNode* p; p = new TNode(IR_ARG, 0, 0, k * 4); p = new TNode(IR_MEM, p, 0); p = new TNode(IR_MOVE, q, p); p = new TNode(IR_SEQ, p, 0); if (l) l->r = p; else t = p; l = p; } return t; } void ExprSeqNode::castTo(DeclSeq* decls, Environ* e, bool cfunc) { if (exprs.size() > decls->size()) ex("Too many parameters"); for (int k = 0; k < decls->size(); ++k) { Decl* d = decls->decls[k]; if (k < exprs.size() && exprs[k]) { if (cfunc && d->type->structType()) { if (exprs[k]->sem_type->structType()) { } else if (exprs[k]->sem_type->intType()) { exprs[k]->sem_type = Type::void_type; } else { ex("Illegal type conversion"); } continue; } exprs[k] = exprs[k]->castTo(d->type, e); } else { if (!d->defType) ex("Not enough parameters"); ExprNode* expr = constValue(d->defType); if (k < exprs.size()) exprs[k] = expr; else exprs.push_back(expr); } } } void ExprSeqNode::castTo(Type* t, Environ* e) { for (int k = 0; k < exprs.size(); ++k) { exprs[k] = exprs[k]->castTo(t, e); } } /////////////////// // Function call // /////////////////// ExprNode* CallNode::semant(Environ* e) { Type* t = e->findType(tag); sem_decl = e->findFunc(ident); if (!sem_decl || !(sem_decl->kind & DECL_FUNC)) ex("Function '" + ident + "' not found"); FuncType* f = sem_decl->type->funcType(); if (t && f->returnType != t) ex("incorrect function return type"); exprs->semant(e); exprs->castTo(f->params, e, f->cfunc); sem_type = f->returnType; return this; } TNode* CallNode::translate(Codegen* g) { FuncType* f = sem_decl->type->funcType(); TNode* t; TNode* l = global("_f" + ident); TNode* r = exprs->translate(g, f->cfunc); if (f->userlib) { l = new TNode(IR_MEM, l); usedfuncs.insert(ident); } if (sem_type == Type::float_type) { t = new TNode(IR_FCALL, l, r, exprs->size() * 4); } else { t = new TNode(IR_CALL, l, r, exprs->size() * 4); } if (f->returnType->stringType()) { if (f->cfunc) { t = call("__bbCStrToStr", t); } } return t; } ///////////////////////// // Variable expression // ///////////////////////// ExprNode* VarExprNode::semant(Environ* e) { var->semant(e); sem_type = var->sem_type; ConstType* c = sem_type->constType(); if (!c) return this; ExprNode* expr = constValue(c); delete this; return expr; } TNode* VarExprNode::translate(Codegen* g) { return var->load(g); } ////////////////////// // Integer constant // ////////////////////// IntConstNode::IntConstNode(int n) : value(n) { sem_type = Type::int_type; } TNode* IntConstNode::translate(Codegen* g) { return new TNode(IR_CONST, 0, 0, value); } int IntConstNode::intValue() { return value; } float IntConstNode::floatValue() { return value; } string IntConstNode::stringValue() { return itoa(value); } //////////////////// // Float constant // //////////////////// FloatConstNode::FloatConstNode(float f) : value(f) { sem_type = Type::float_type; } TNode* FloatConstNode::translate(Codegen* g) { return new TNode(IR_CONST, 0, 0, *(int*)&value); } int FloatConstNode::intValue() { float flt = value; int temp; _control87(_RC_NEAR | _PC_24 | _EM_INVALID | _EM_ZERODIVIDE | _EM_OVERFLOW | _EM_UNDERFLOW | _EM_INEXACT | _EM_DENORMAL, 0xfffff); _asm { fld[flt]; fistp[temp]; } _control87(_CW_DEFAULT, 0xfffff); return temp; } float FloatConstNode::floatValue() { return value; } string FloatConstNode::stringValue() { return ftoa(value); } ///////////////////// // String constant // ///////////////////// StringConstNode::StringConstNode(const string& s) : value(s) { sem_type = Type::string_type; } TNode* StringConstNode::translate(Codegen* g) { string lab = genLabel(); g->s_data(value, lab); return call("__bbStrConst", global(lab)); } int StringConstNode::intValue() { return atoi(value); } float StringConstNode::floatValue() { return (float)atof(value); } string StringConstNode::stringValue() { return value; } //////////////////// // Unary operator // //////////////////// ExprNode* UniExprNode::semant(Environ* e) { expr = expr->semant(e); sem_type = expr->sem_type; if (sem_type != Type::int_type && sem_type != Type::float_type) ex("Illegal operator for type"); if (ConstNode* c = expr->constNode()) { ExprNode* e; if (sem_type == Type::int_type) { switch (op) { case '+': e = new IntConstNode(+c->intValue()); break; case '-': e = new IntConstNode(-c->intValue()); break; case ABS: e = new IntConstNode(c->intValue() >= 0 ? c->intValue() : -c->intValue()); break; case SGN: e = new IntConstNode(c->intValue() > 0 ? 1 : (c->intValue() < 0 ? -1 : 0)); break; } } else { switch (op) { case '+': e = new FloatConstNode(+c->floatValue()); break; case '-': e = new FloatConstNode(-c->floatValue()); break; case ABS: e = new FloatConstNode(c->floatValue() >= 0 ? c->floatValue() : -c->floatValue()); break; case SGN: e = new FloatConstNode(c->floatValue() > 0 ? 1 : (c->floatValue() < 0 ? -1 : 0)); break; } } delete this; return e = nullptr; } return this; } TNode* UniExprNode::translate(Codegen* g) { int n = 0; TNode* l = expr->translate(g); if (sem_type == Type::int_type) { switch (op) { case '+': return l; case '-': n = IR_NEG; break; case ABS: return call("__bbAbs", l); case SGN: return call("__bbSgn", l); } } else { switch (op) { case '+': return l; case '-': n = IR_FNEG; break; case ABS: return fcall("__bbFAbs", l); case SGN: return fcall("__bbFSgn", l); } } return new TNode(n, l, 0); } ///////////////////////////////////////////////////// // boolean expression - accepts ints, returns ints // ///////////////////////////////////////////////////// ExprNode* BinExprNode::semant(Environ* e) { lhs = lhs->semant(e); lhs = lhs->castTo(Type::int_type, e); rhs = rhs->semant(e); rhs = rhs->castTo(Type::int_type, e); ConstNode *lc = lhs->constNode(), *rc = rhs->constNode(); if (lc && rc) { ExprNode* expr = nullptr; switch (op) { case AND: expr = new IntConstNode(lc->intValue() & rc->intValue()); break; case OR: expr = new IntConstNode(lc->intValue() | rc->intValue()); break; case XOR: expr = new IntConstNode(lc->intValue() ^ rc->intValue()); break; case SHL: expr = new IntConstNode(lc->intValue() << rc->intValue()); break; case SHR: expr = new IntConstNode((unsigned)lc->intValue() >> rc->intValue()); break; case SAR: expr = new IntConstNode(lc->intValue() >> rc->intValue()); break; } delete this; return expr; } sem_type = Type::int_type; return this; } TNode* BinExprNode::translate(Codegen* g) { TNode* l = lhs->translate(g); TNode* r = rhs->translate(g); int n = 0; switch (op) { case AND: n = IR_AND; break; case OR: n = IR_OR; break; case XOR: n = IR_XOR; break; case SHL: n = IR_SHL; break; case SHR: n = IR_SHR; break; case SAR: n = IR_SAR; break; } return new TNode(n, l, r); } /////////////////////////// // arithmetic expression // /////////////////////////// ExprNode* ArithExprNode::semant(Environ* e) { lhs = lhs->semant(e); rhs = rhs->semant(e); if (lhs->sem_type->structType() || rhs->sem_type->structType()) { ex("Arithmetic operator cannot be applied to custom type objects"); } if (lhs->sem_type == Type::string_type || rhs->sem_type == Type::string_type) { //one side is a string - only + operator... if (op != '+') ex("Operator cannot be applied to strings"); sem_type = Type::string_type; } else if (op == '^' || lhs->sem_type == Type::float_type || rhs->sem_type == Type::float_type) { //It's ^, or one side is a float sem_type = Type::float_type; } else { //must be 2 ints sem_type = Type::int_type; } lhs = lhs->castTo(sem_type, e); rhs = rhs->castTo(sem_type, e); ConstNode *lc = lhs->constNode(), *rc = rhs->constNode(); if (rc && (op == '/' || op == MOD)) { if ((sem_type == Type::int_type && !rc->intValue()) || (sem_type == Type::float_type && !rc->floatValue())) { ex("Division by zero"); } } if (lc && rc) { ExprNode* expr = nullptr; if (sem_type == Type::string_type) { expr = new StringConstNode(lc->stringValue() + rc->stringValue()); } else if (sem_type == Type::int_type) { switch (op) { case '+': expr = new IntConstNode(lc->intValue() + rc->intValue()); break; case '-': expr = new IntConstNode(lc->intValue() - rc->intValue()); break; case '*': expr = new IntConstNode(lc->intValue() * rc->intValue()); break; case '/': expr = new IntConstNode(lc->intValue() / rc->intValue()); break; case MOD: expr = new IntConstNode(lc->intValue() % rc->intValue()); break; } } else { switch (op) { case '+': expr = new FloatConstNode(lc->floatValue() + rc->floatValue()); break; case '-': expr = new FloatConstNode(lc->floatValue() - rc->floatValue()); break; case '*': expr = new FloatConstNode(lc->floatValue() * rc->floatValue()); break; case '/': expr = new FloatConstNode(lc->floatValue() / rc->floatValue()); break; case MOD: expr = new FloatConstNode(fmod(lc->floatValue(), rc->floatValue())); break; case '^': expr = new FloatConstNode(pow(lc->floatValue(), rc->floatValue())); break; } } delete this; return expr; } return this; } TNode* ArithExprNode::translate(Codegen* g) { TNode* l = lhs->translate(g); TNode* r = rhs->translate(g); if (sem_type == Type::string_type) { return call("__bbStrConcat", l, r); } int n = 0; if (sem_type == Type::int_type) { switch (op) { case '+': n = IR_ADD; break; case '-': n = IR_SUB; break; case '*': n = IR_MUL; break; case '/': n = IR_DIV; break; case MOD: return call("__bbMod", l, r); } } else { switch (op) { case '+': n = IR_FADD; break; case '-': n = IR_FSUB; break; case '*': n = IR_FMUL; break; case '/': n = IR_FDIV; break; case MOD: return fcall("__bbFMod", l, r); case '^': return fcall("__bbFPow", l, r); } } return new TNode(n, l, r); } ///////////////////////// // relation expression // ///////////////////////// ExprNode* RelExprNode::semant(Environ* e) { lhs = lhs->semant(e); rhs = rhs->semant(e); if (lhs->sem_type->structType() || rhs->sem_type->structType()) { if (op != '=' && op != NE) ex("Illegal operator for custom type objects"); opType = lhs->sem_type != Type::null_type ? lhs->sem_type : rhs->sem_type; } else if (lhs->sem_type == Type::string_type || rhs->sem_type == Type::string_type) { opType = Type::string_type; } else if (lhs->sem_type == Type::float_type || rhs->sem_type == Type::float_type) { opType = Type::float_type; } else { opType = Type::int_type; } sem_type = Type::int_type; lhs = lhs->castTo(opType, e); rhs = rhs->castTo(opType, e); ConstNode *lc = lhs->constNode(), *rc = rhs->constNode(); if (lc && rc) { ExprNode* expr = nullptr; if (opType == Type::string_type) { switch (op) { case '<': expr = new IntConstNode(lc->stringValue() < rc->stringValue()); break; case '=': expr = new IntConstNode(lc->stringValue() == rc->stringValue()); break; case '>': expr = new IntConstNode(lc->stringValue() > rc->stringValue()); break; case LE: expr = new IntConstNode(lc->stringValue() <= rc->stringValue()); break; case NE: expr = new IntConstNode(lc->stringValue() != rc->stringValue()); break; case GE: expr = new IntConstNode(lc->stringValue() >= rc->stringValue()); break; } } else if (opType == Type::float_type) { switch (op) { case '<': expr = new IntConstNode(lc->floatValue() < rc->floatValue()); break; case '=': expr = new IntConstNode(lc->floatValue() == rc->floatValue()); break; case '>': expr = new IntConstNode(lc->floatValue() > rc->floatValue()); break; case LE: expr = new IntConstNode(lc->floatValue() <= rc->floatValue()); break; case NE: expr = new IntConstNode(lc->floatValue() != rc->floatValue()); break; case GE: expr = new IntConstNode(lc->floatValue() >= rc->floatValue()); break; } } else { switch (op) { case '<': expr = new IntConstNode(lc->intValue() < rc->intValue()); break; case '=': expr = new IntConstNode(lc->intValue() == rc->intValue()); break; case '>': expr = new IntConstNode(lc->intValue() > rc->intValue()); break; case LE: expr = new IntConstNode(lc->intValue() <= rc->intValue()); break; case NE: expr = new IntConstNode(lc->intValue() != rc->intValue()); break; case GE: expr = new IntConstNode(lc->intValue() >= rc->intValue()); break; } } delete this; return expr; } return this; } TNode* RelExprNode::translate(Codegen* g) { TNode* l = lhs->translate(g); TNode* r = rhs->translate(g); return compare(op, l, r, opType); } //////////////////// // New expression // //////////////////// ExprNode* NewNode::semant(Environ* e) { sem_type = e->findType(ident); if (!sem_type) ex("custom type name not found"); if (sem_type->structType() == 0) ex("type is not a custom type"); return this; } TNode* NewNode::translate(Codegen* g) { return call("__bbObjNew", global("_t" + ident)); } //////////////////// // First of class // //////////////////// ExprNode* FirstNode::semant(Environ* e) { sem_type = e->findType(ident); if (!sem_type) ex("custom type name name not found"); return this; } TNode* FirstNode::translate(Codegen* g) { return call("__bbObjFirst", global("_t" + ident)); } /////////////////// // Last of class // /////////////////// ExprNode* LastNode::semant(Environ* e) { sem_type = e->findType(ident); if (!sem_type) ex("custom type name not found"); return this; } TNode* LastNode::translate(Codegen* g) { return call("__bbObjLast", global("_t" + ident)); } //////////////////// // Next of object // //////////////////// ExprNode* AfterNode::semant(Environ* e) { expr = expr->semant(e); if (expr->sem_type == Type::null_type) ex("'After' cannot be used on 'Null'"); if (expr->sem_type->structType() == 0) ex("'After' must be used with a custom type object"); sem_type = expr->sem_type; return this; } TNode* AfterNode::translate(Codegen* g) { TNode* t = expr->translate(g); if (g->debug) t = jumpf(t, "__bbNullObjEx"); return call("__bbObjNext", t); } //////////////////// // Prev of object // //////////////////// ExprNode* BeforeNode::semant(Environ* e) { expr = expr->semant(e); if (expr->sem_type == Type::null_type) ex("'Before' cannot be used with 'Null'"); if (expr->sem_type->structType() == 0) ex("'Before' must be used with a custom type object"); sem_type = expr->sem_type; return this; } TNode* BeforeNode::translate(Codegen* g) { TNode* t = expr->translate(g); if (g->debug) t = jumpf(t, "__bbNullObjEx"); return call("__bbObjPrev", t); } ///////////////// // Null object // ///////////////// ExprNode* NullNode::semant(Environ* e) { sem_type = Type::null_type; return this; } TNode* NullNode::translate(Codegen* g) { return new TNode(IR_CONST, 0, 0, 0); } ///////////////// // Object cast // ///////////////// ExprNode* ObjectCastNode::semant(Environ* e) { expr = expr->semant(e); expr = expr->castTo(Type::int_type, e); sem_type = e->findType(type_ident); if (!sem_type) ex("custom type name not found"); if (!sem_type->structType()) ex("type is not a custom type"); return this; } TNode* ObjectCastNode::translate(Codegen* g) { TNode* t = expr->translate(g); t = call("__bbObjFromHandle", t, global("_t" + sem_type->structType()->ident)); return t; } /////////////////// // Object Handle // /////////////////// ExprNode* ObjectHandleNode::semant(Environ* e) { expr = expr->semant(e); if (!expr->sem_type->structType()) ex("'ObjectHandle' must be used with an object"); sem_type = Type::int_type; return this; } TNode* ObjectHandleNode::translate(Codegen* g) { TNode* t = expr->translate(g); return call("__bbObjToHandle", t); }