// ------------------------------------------------------------ Evaluate one operator. void dispatchEval( Eval ev ) { double result; Operand rightp = topStack( ev->Ands ); popStack( ev->Ands ); Operand leftp = topStack( ev->Ands ); popStack( ev->Ands ); double right = value( rightp ); freeOperand( rightp ); double left = value( leftp ); freeOperand( leftp ); Operator op = topStack( ev->Ators); popStack( ev->Ators ); ev->numbin--; printf( " Evaluating: %g%c%g\n", left, symbolOperator( op ), right ); switch ( symbolOperator( op ) ) { case '+': result = left + right; break; case '-': result = left - right; break; case '*': result = left * right; break; case '/': result = left / right; break; case '%': result = fmod(left, right); break; case '^': result = pow (left, right); break; default: result = HUGE_VAL; /* shouldn't occur */ } freeOperator( op ); Operand And = newOperand( result ); pushStack( ev->Ands, And ); }
std::string Value::toString() const { switch (kind()) { case SELF: return "self"; case THIS: return "this"; case CONSTANT: return makeString("Constant(%s)", constant().toString().c_str()); case ALIAS: return makeString("Alias(alias: %s, templateArguments: %s)", alias().toString().c_str(), makeArrayString(aliasTemplateArguments()).c_str()); case PREDICATE: return makeString("Predicate(%s)", predicate().toString().c_str()); case LOCALVAR: return makeString("LocalVar(%s)", localVar().toString().c_str()); case REINTERPRET: return makeString("Reinterpret(value: %s)", reinterpretOperand().toString().c_str()); case DEREF_REFERENCE: return makeString("DerefReference(%s)", derefOperand().toString().c_str()); case TERNARY: return makeString("Ternary(cond: %s, ifTrue: %s, ifFalse: %s)", ternaryCondition().toString().c_str(), ternaryIfTrue().toString().c_str(), ternaryIfFalse().toString().c_str()); case CAST: return makeString("Cast(value: %s, targetType: %s)", castOperand().toString().c_str(), castTargetType()->toString().c_str()); case POLYCAST: return makeString("PolyCast(value: %s, targetType: %s)", polyCastOperand().toString().c_str(), polyCastTargetType()->toString().c_str()); case INTERNALCONSTRUCT: return makeString("InternalConstruct(args: %s)", makeArrayString(internalConstructParameters()).c_str()); case MEMBERACCESS: return makeString("MemberAccess(object: %s, var: %s)", memberAccessObject().toString().c_str(), memberAccessVar().toString().c_str()); case BIND_REFERENCE: return makeString("BindReference(value: %s)", bindReferenceOperand().toString().c_str()); case TYPEREF: return makeString("TypeRef(targetType: %s)", typeRefType()->toString().c_str()); case TEMPLATEVARREF: return makeString("TemplateVarRef(templateVar: %s)", templateVar()->toString().c_str()); case CALL: return makeString("Call(funcValue: %s, args: %s)", callValue().toString().c_str(), makeArrayString(callParameters()).c_str()); case FUNCTIONREF: return makeString("FunctionRef(name: %s, type: %s, parentType: %s, templateArgs: %s)", functionRefFunction().fullName().toString().c_str(), type()->toString().c_str(), functionRefParentType() != nullptr ? functionRefParentType()->toString().c_str() : "[NONE]", makeArrayString(functionRefTemplateArguments()).c_str()); case TEMPLATEFUNCTIONREF: return makeString("TemplateFunctionRef(name: %s, parentType: %s)", templateFunctionRefName().c_str(), templateFunctionRefParentType()->toString().c_str()); case METHODOBJECT: return makeString("MethodObject(method: %s, object: %s)", methodObject().toString().c_str(), methodOwner().toString().c_str()); case INTERFACEMETHODOBJECT: return makeString("InterfaceMethodObject(method: %s, object: %s)", interfaceMethodObject().toString().c_str(), interfaceMethodOwner().toString().c_str()); case STATICINTERFACEMETHODOBJECT: return makeString("StaticInterfaceMethodObject(method: %s, typeRef: %s)", staticInterfaceMethodObject().toString().c_str(), staticInterfaceMethodOwner().toString().c_str()); case CAPABILITYTEST: return makeString("CapabilityTest(checkType: %s, capabilityType: %s)", capabilityTestCheckType()->toString().c_str(), capabilityTestCapabilityType()->toString().c_str()); case Value::ARRAYLITERAL: return makeString("ArrayLiteral(type: %s, values: %s)", type()->toString().c_str(), makeArrayString(arrayLiteralValues()).c_str()); case NEW: return makeString("New(placementArg: %s, operand: %s)", newPlacementArg().toString().c_str(), newOperand().toString().c_str()); case CASTDUMMYOBJECT: return makeString("[CAST DUMMY OBJECT (FOR SEMANTIC ANALYSIS)](type: %s)", type()->toString().c_str()); } locic_unreachable("Unknown value kind."); }
bool Value::operator==(const Value& value) const { if (kind() != value.kind()) { return false; } if (type() != value.type()) { return false; } switch (value.kind()) { case Value::SELF: return true; case Value::THIS: return true; case Value::CONSTANT: return constant() == value.constant(); case Value::ALIAS: return &(alias()) == &(value.alias()) && aliasTemplateArguments() == value.aliasTemplateArguments(); case Value::PREDICATE: return predicate() == value.predicate(); case Value::LOCALVAR: return &(localVar()) == &(value.localVar()); case Value::REINTERPRET: return reinterpretOperand() == value.reinterpretOperand(); case Value::DEREF_REFERENCE: return derefOperand() == value.derefOperand(); case Value::TERNARY: return ternaryCondition() == value.ternaryCondition() && ternaryIfTrue() == value.ternaryIfTrue() && ternaryIfFalse() == value.ternaryIfFalse(); case Value::CAST: return castTargetType() == value.castTargetType() && castOperand() == value.castOperand(); case Value::POLYCAST: return polyCastTargetType() == value.polyCastTargetType() && polyCastOperand() == value.polyCastOperand(); case Value::INTERNALCONSTRUCT: return internalConstructParameters() == value.internalConstructParameters(); case Value::MEMBERACCESS: return memberAccessObject() == value.memberAccessObject() && &(memberAccessVar()) == &(value.memberAccessVar()); case Value::BIND_REFERENCE: return bindReferenceOperand() == value.bindReferenceOperand(); case Value::TYPEREF: return typeRefType() == value.typeRefType(); case Value::TEMPLATEVARREF: return templateVar() == value.templateVar(); case Value::CALL: return callValue() == value.callValue() && callParameters() == value.callParameters(); case Value::FUNCTIONREF: return functionRefParentType() == value.functionRefParentType() && &(functionRefFunction()) == &(value.functionRefFunction()) && functionRefTemplateArguments() == value.functionRefTemplateArguments(); case Value::TEMPLATEFUNCTIONREF: return templateFunctionRefParentType() == value.templateFunctionRefParentType() && templateFunctionRefName() == value.templateFunctionRefName() && templateFunctionRefFunctionType() == value.templateFunctionRefFunctionType(); case Value::METHODOBJECT: return methodObject() == value.methodObject() && methodOwner() == value.methodOwner(); case Value::INTERFACEMETHODOBJECT: return interfaceMethodObject() == value.interfaceMethodObject() && interfaceMethodOwner() == value.interfaceMethodOwner(); case Value::STATICINTERFACEMETHODOBJECT: return staticInterfaceMethodObject() == value.staticInterfaceMethodObject() && staticInterfaceMethodOwner() == value.staticInterfaceMethodOwner(); case Value::CAPABILITYTEST: return capabilityTestCheckType() == value.capabilityTestCheckType() && capabilityTestCapabilityType() == value.capabilityTestCapabilityType(); case Value::ARRAYLITERAL: return arrayLiteralValues() == value.arrayLiteralValues(); case Value::NEW: return newPlacementArg() == value.newPlacementArg() && newOperand() == value.newOperand(); case Value::CASTDUMMYOBJECT: return true; } locic_unreachable("Unknown value kind."); }
size_t Value::hash() const { Hasher hasher; hasher.add(kind()); hasher.add(type()); switch (kind()) { case Value::SELF: break; case Value::THIS: break; case Value::CONSTANT: hasher.add(constant()); break; case Value::ALIAS: hasher.add(&(alias())); hasher.add(aliasTemplateArguments().size()); for (const auto& argument: aliasTemplateArguments()) { hasher.add(argument); } break; case Value::PREDICATE: hasher.add(predicate()); break; case Value::LOCALVAR: hasher.add(&(localVar())); break; case Value::REINTERPRET: hasher.add(reinterpretOperand()); break; case Value::DEREF_REFERENCE: hasher.add(derefOperand()); break; case Value::TERNARY: hasher.add(ternaryCondition()); hasher.add(ternaryIfTrue()); hasher.add(ternaryIfFalse()); break; case Value::CAST: hasher.add(castTargetType()); hasher.add(castOperand()); break; case Value::POLYCAST: hasher.add(polyCastTargetType()); hasher.add(polyCastOperand()); break; case Value::INTERNALCONSTRUCT: hasher.add(internalConstructParameters().size()); for (const auto& param: internalConstructParameters()) { hasher.add(param); } break; case Value::MEMBERACCESS: hasher.add(memberAccessObject()); hasher.add(&(memberAccessVar())); break; case Value::BIND_REFERENCE: hasher.add(bindReferenceOperand()); break; case Value::TYPEREF: hasher.add(typeRefType()); break; case Value::TEMPLATEVARREF: hasher.add(templateVar()); break; case Value::CALL: hasher.add(callValue()); hasher.add(callParameters().size()); for (const auto& param: callParameters()) { hasher.add(param); } break; case Value::FUNCTIONREF: hasher.add(functionRefParentType()); hasher.add(&(functionRefFunction())); hasher.add(functionRefTemplateArguments().size()); for (const auto& arg: functionRefTemplateArguments()) { hasher.add(arg); } break; case Value::TEMPLATEFUNCTIONREF: hasher.add(templateFunctionRefParentType()); hasher.add(templateFunctionRefName()); hasher.add(templateFunctionRefFunctionType()); break; case Value::METHODOBJECT: hasher.add(methodObject()); hasher.add(methodOwner()); break; case Value::INTERFACEMETHODOBJECT: hasher.add(interfaceMethodObject()); hasher.add(interfaceMethodOwner()); break; case Value::STATICINTERFACEMETHODOBJECT: hasher.add(staticInterfaceMethodObject()); hasher.add(staticInterfaceMethodOwner()); break; case Value::CAPABILITYTEST: hasher.add(capabilityTestCheckType()); hasher.add(capabilityTestCapabilityType()); break; case Value::ARRAYLITERAL: hasher.add(arrayLiteralValues().size()); for (const auto& value: arrayLiteralValues()) { hasher.add(value); } break; case Value::NEW: hasher.add(newPlacementArg()); hasher.add(newOperand()); break; case Value::CASTDUMMYOBJECT: break; } return hasher.get(); }
std::string Value::toDiagString() const { switch (kind()) { case SELF: return "self"; case THIS: return "this"; case CONSTANT: return constant().toString(); case ALIAS: return alias().toString(); case PREDICATE: return predicate().toString(); case LOCALVAR: return localVar().name().asStdString(); case REINTERPRET: return reinterpretOperand().toDiagString(); case DEREF_REFERENCE: return makeString("<deref> %s", derefOperand().toDiagString().c_str()); case TERNARY: return makeString("%s ? %s : %s", ternaryCondition().toDiagString().c_str(), ternaryIfTrue().toDiagString().c_str(), ternaryIfFalse().toDiagString().c_str()); case CAST: return castOperand().toDiagString(); case POLYCAST: return polyCastOperand().toDiagString(); case INTERNALCONSTRUCT: return makeString("@(%s)", makeArrayString(internalConstructParameters()).c_str()); case MEMBERACCESS: return makeString("%s.%s", memberAccessObject().toDiagString().c_str(), memberAccessVar().name().c_str()); case BIND_REFERENCE: return makeString("<bind> %s", bindReferenceOperand().toDiagString().c_str()); case TYPEREF: return typeRefType()->toDiagString(); case TEMPLATEVARREF: return templateVar()->fullName().last().asStdString(); case CALL: return makeString("%s(%s)", callValue().toDiagString().c_str(), makeArrayString(callParameters()).c_str()); case FUNCTIONREF: return functionRefFunction().fullName().toString(); case TEMPLATEFUNCTIONREF: return makeString("%s::%s", templateFunctionRefParentType()->toDiagString().c_str(), templateFunctionRefName().c_str()); case METHODOBJECT: return makeString("%s.%s", methodOwner().toDiagString().c_str(), methodObject().toDiagString().c_str()); case INTERFACEMETHODOBJECT: return makeString("%s.%s", interfaceMethodOwner().toDiagString().c_str(), interfaceMethodObject().toDiagString().c_str()); case STATICINTERFACEMETHODOBJECT: return makeString("%s.%s", staticInterfaceMethodOwner().toDiagString().c_str(), staticInterfaceMethodObject().toDiagString().c_str()); case CAPABILITYTEST: return makeString("%s : %s", capabilityTestCheckType()->toDiagString().c_str(), capabilityTestCapabilityType()->toDiagString().c_str()); case Value::ARRAYLITERAL: return makeString("{ %s }", makeArrayString(arrayLiteralValues()).c_str()); case NEW: return makeString("new(%s) %s", newPlacementArg().toDiagString().c_str(), newOperand().toDiagString().c_str()); case CASTDUMMYOBJECT: locic_unreachable("Shouldn't reach CASTDUMMYOBJECT."); } locic_unreachable("Unknown value kind."); }
void newOperandOrFunctionCall(int index) { // Retrieve symbol SymbolTableRow* functionSymbol = getSymbol(index, symbolTableStack->integer); // Determine if it is a function call or a variable if (functionSymbol->category == scVariable || functionSymbol->category == scParameter) newOperand(opdtVariable, index); else newFunctionOperator(index); }
//------------------------------------------------ Read input and evaluate expression. double evaluateEval(Eval ev) { Intype next; // Classification of next input character. char inSymbol; // Read input operators into this. Operator inOp; // Operator object constructed from inSymbol. double inNumVal; // Read input operands into this. Operand And; // Operand value int numread; int n; for (;;) { next = classifyEval(ev); switch (next) { case number: n = sscanf(ev->instream, "%lg%n", &inNumVal, &numread); ev->instream += numread; if (n!=1 || sizeStack(ev->Ands) != ev->numbin) return expErrorEval(ev); And = newOperand(inNumVal); pushStack(ev->Ands, And); break; case op: if (sizeStack(ev->Ands) != ev->numbin+1) return expErrorEval(ev); inSymbol = *(ev->instream++); inOp = newOperator(inSymbol); forceEval(ev, precedenceOperator(inOp) ); pushStack(ev->Ators, inOp); ev->numbin++; break; case lpar: if (sizeStack(ev->Ands) != ev->numbin) return expErrorEval(ev); inSymbol = *(ev->instream++); inOp = newOperator(inSymbol); // put left paren on Ators stack pushStack(ev->Ators, inOp); break; case rpar: n = sscanf(ev->instream, " %c%n", &inSymbol, &numread); ev->instream += numread; if (sizeStack(ev->Ands) != ev->numbin+1) return expErrorEval(ev); forceEval(ev, 0); if (isemptyStack(ev->Ators)) expErrorEval(ev); // too many right parens Operator op = topStack(ev->Ators); // remove left paren operator from Ators stack freeOperator(op); popStack(ev->Ators); break; case end: if (sizeStack(ev->Ands) != ev->numbin+1) return expErrorEval(ev); forceEval(ev, 0); if (!isemptyStack(ev->Ators)) return expErrorEval(ev); And = topStack(ev->Ands); popStack(ev->Ands); double retval = value(And); freeOperand(And); return retval; break; case bad: default: return expErrorEval(ev); } } }