#include "std.h" #include "nodes.h" #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 = d_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 = d_new IntConstNode(c->intValue()); else if (type == Type::float_type) e = d_new FloatConstNode(c->floatValue()); else e = d_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 d_new TNode(IR_CAST, t, 0); } if (expr->sem_type == Type::int_type && sem_type == Type::float_type) { //int->float return d_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 = d_new TNode(IR_MEM, q); } else if (ty == Type::void_type) { q = d_new TNode(IR_MEM, add(q, iconst(4))); } } TNode *p; p = d_new TNode(IR_ARG, 0, 0, k * 4); p = d_new TNode(IR_MEM, p, 0); p = d_new TNode(IR_MOVE, q, p); p = d_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 = d_new TNode(IR_MEM, l); usedfuncs.insert(ident); } if (sem_type == Type::float_type) { t = d_new TNode(IR_FCALL, l, r, exprs->size() * 4); } else { t = d_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 d_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 d_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 = d_new IntConstNode(+c->intValue()); break; case '-':e = d_new IntConstNode(-c->intValue()); break; case ABS:e = d_new IntConstNode(c->intValue() >= 0 ? c->intValue() : -c->intValue()); break; case SGN:e = d_new IntConstNode(c->intValue() > 0 ? 1 : (c->intValue() < 0 ? -1 : 0)); break; } } else { switch (op) { case '+':e = d_new FloatConstNode(+c->floatValue()); break; case '-':e = d_new FloatConstNode(-c->floatValue()); break; case ABS:e = d_new FloatConstNode(c->floatValue() >= 0 ? c->floatValue() : -c->floatValue()); break; case SGN:e = d_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 d_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 = d_new IntConstNode(lc->intValue() & rc->intValue()); break; case OR: expr = d_new IntConstNode(lc->intValue() | rc->intValue()); break; case XOR:expr = d_new IntConstNode(lc->intValue() ^ rc->intValue()); break; case SHL:expr = d_new IntConstNode(lc->intValue() << rc->intValue()); break; case SHR:expr = d_new IntConstNode((unsigned)lc->intValue() >> rc->intValue()); break; case SAR:expr = d_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 d_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 = d_new StringConstNode(lc->stringValue() + rc->stringValue()); } else if (sem_type == Type::int_type) { switch (op) { case '+':expr = d_new IntConstNode(lc->intValue() + rc->intValue()); break; case '-':expr = d_new IntConstNode(lc->intValue() - rc->intValue()); break; case '*':expr = d_new IntConstNode(lc->intValue()*rc->intValue()); break; case '/':expr = d_new IntConstNode(lc->intValue() / rc->intValue()); break; case MOD:expr = d_new IntConstNode(lc->intValue() % rc->intValue()); break; } } else { switch (op) { case '+':expr = d_new FloatConstNode(lc->floatValue() + rc->floatValue()); break; case '-':expr = d_new FloatConstNode(lc->floatValue() - rc->floatValue()); break; case '*':expr = d_new FloatConstNode(lc->floatValue()*rc->floatValue()); break; case '/':expr = d_new FloatConstNode(lc->floatValue() / rc->floatValue()); break; case MOD:expr = d_new FloatConstNode(fmod(lc->floatValue(), rc->floatValue())); break; case '^':expr = d_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 d_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 = d_new IntConstNode(lc->stringValue() < rc->stringValue()); break; case '=':expr = d_new IntConstNode(lc->stringValue() == rc->stringValue()); break; case '>':expr = d_new IntConstNode(lc->stringValue() > rc->stringValue()); break; case LE: expr = d_new IntConstNode(lc->stringValue() <= rc->stringValue()); break; case NE: expr = d_new IntConstNode(lc->stringValue() != rc->stringValue()); break; case GE: expr = d_new IntConstNode(lc->stringValue() >= rc->stringValue()); break; } } else if (opType == Type::float_type) { switch (op) { case '<':expr = d_new IntConstNode(lc->floatValue() < rc->floatValue()); break; case '=':expr = d_new IntConstNode(lc->floatValue() == rc->floatValue()); break; case '>':expr = d_new IntConstNode(lc->floatValue() > rc->floatValue()); break; case LE: expr = d_new IntConstNode(lc->floatValue() <= rc->floatValue()); break; case NE: expr = d_new IntConstNode(lc->floatValue() != rc->floatValue()); break; case GE: expr = d_new IntConstNode(lc->floatValue() >= rc->floatValue()); break; } } else { switch (op) { case '<':expr = d_new IntConstNode(lc->intValue() < rc->intValue()); break; case '=':expr = d_new IntConstNode(lc->intValue() == rc->intValue()); break; case '>':expr = d_new IntConstNode(lc->intValue() > rc->intValue()); break; case LE: expr = d_new IntConstNode(lc->intValue() <= rc->intValue()); break; case NE: expr = d_new IntConstNode(lc->intValue() != rc->intValue()); break; case GE: expr = d_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 d_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); }