void InsetMathChar::metrics(MetricsInfo & mi, Dimension & dim) const { #if 1 if (char_ == '=' && has_math_fonts) { FontSetChanger dummy(mi.base, "cmr"); dim = theFontMetrics(mi.base.font).dimension(char_); } else if ((char_ == '>' || char_ == '<') && has_math_fonts) { FontSetChanger dummy(mi.base, "cmm"); dim = theFontMetrics(mi.base.font).dimension(char_); } else if (!slanted(char_) && mi.base.fontname == "mathnormal") { ShapeChanger dummy(mi.base.font, UP_SHAPE); dim = theFontMetrics(mi.base.font).dimension(char_); } else { frontend::FontMetrics const & fm = theFontMetrics(mi.base.font); dim = fm.dimension(char_); kerning_ = fm.rbearing(char_) - dim.wid; } int const em = mathed_char_width(mi.base.font, 'M'); if (isBinaryOp(char_)) dim.wid += static_cast<int>(0.5*em+0.5); else if (char_ == '\'') dim.wid += static_cast<int>(0.1667*em+0.5); #else whichFont(font_, code_, mi); dim = theFontMetrics(font_).dimension(char_); if (isBinaryOp(char_, code_)) dim.wid += 2 * theFontMetrics(font_).width(' '); lyxerr << "InsetMathChar::metrics: " << dim << endl; #endif }
void InsetMathChar::draw(PainterInfo & pi, int x, int y) const { //lyxerr << "drawing '" << char_ << "' font: " << pi.base.fontname << endl; int const em = mathed_char_width(pi.base.font, 'M'); if (isBinaryOp(char_)) x += static_cast<int>(0.25*em+0.5); else if (char_ == '\'') x += static_cast<int>(0.0833*em+0.5); #if 1 if (char_ == '=' && has_math_fonts) { FontSetChanger dummy(pi.base, "cmr"); pi.draw(x, y, char_); } else if ((char_ == '>' || char_ == '<') && has_math_fonts) { FontSetChanger dummy(pi.base, "cmm"); pi.draw(x, y, char_); } else if (!slanted(char_) && pi.base.fontname == "mathnormal") { ShapeChanger dummy(pi.base.font, UP_SHAPE); pi.draw(x, y, char_); } else { pi.draw(x, y, char_); } #else drawChar(pain, font_, x, y, char_); #endif }
Token Parser::expr(Expression &exp, int precendence) { primary(exp); Token binOp; nextToken(); getToken(binOp); int limit = -1; if (isBinaryOp(binOp)) limit = priority[binOp.kindOf].left; while(isBinaryOp(binOp) && limit >= precendence) { Expression exp1; nextToken(); Token tok1 = expr(exp1,priority[binOp.kindOf].right); compileBinExp(exp,exp1,binOp); binOp = tok1; //getToken(token); //exp = exp1; } return binOp; }
static AIExpType_t *makeExpression( AIOp_t *op, AIExpType_t *exp1, AIExpType_t *exp2 ) { if ( isUnaryOp( op->opType ) ) { AIUnaryOp_t *u = ( AIUnaryOp_t * ) op; u->exp = exp1; } else if ( isBinaryOp( op->opType ) ) { AIBinaryOp_t *b = ( AIBinaryOp_t * ) op; b->exp1 = exp1; b->exp2 = exp2; } return ( AIExpType_t * ) op; }
static AIExpType_t *ReadConditionExpression( pc_token_list **list, AIOpType_t op2 ) { AIExpType_t *t; AIOpType_t op; if ( !*list ) { Log::Warn( "Unexpected end of file" ); return nullptr; } t = Primary( list ); if ( !t ) { return nullptr; } op = opTypeFromToken( &(*list)->token ); while ( isBinaryOp( op ) && opCompare( op, op2 ) >= 0 ) { AIExpType_t *t1; pc_token_list *prev = *list; AIOp_t *exp = newOp( *list ); *list = (*list)->next; t1 = ReadConditionExpression( list, op ); if ( !t1 ) { Log::Warn( "Missing right operand for %s on line %d", opTypeToString( op ), prev->token.line ); FreeExpression( t ); FreeOp( exp ); return nullptr; } t = makeExpression( exp, t, t1 ); op = opTypeFromToken( &(*list)->token ); } return t; }
void FreeOp( AIOp_t *op ) { if ( !op ) { return; } if ( isBinaryOp( op->opType ) ) { AIBinaryOp_t *b = ( AIBinaryOp_t * ) op; FreeExpression( b->exp1 ); FreeExpression( b->exp2 ); } else if ( isUnaryOp( op->opType ) ) { AIUnaryOp_t *u = ( AIUnaryOp_t * ) op; FreeExpression( u->exp ); } BG_Free( op ); }
static AIOp_t *newOp( pc_token_list *list ) { pc_token_list *current = list; AIOp_t *ret = nullptr; AIOpType_t op = opTypeFromToken( ¤t->token ); if ( isBinaryOp( op ) ) { AIBinaryOp_t *b = ( AIBinaryOp_t * ) BG_Alloc( sizeof( *b ) ); b->opType = op; ret = ( AIOp_t * ) b; } else if ( isUnaryOp( op ) ) { AIUnaryOp_t *u = ( AIUnaryOp_t * ) BG_Alloc( sizeof( *u ) ); u->opType = op; ret = ( AIOp_t * ) u; } return ret; }
llvm::Value* genFloatPrimitiveMethodCall(Function& function, const SEM::Type* type, const String& methodName, const SEM::FunctionType functionType, llvm::ArrayRef<SEM::Value> templateArgs, PendingResultArray args, llvm::Value* const hintResultValue) { auto& module = function.module(); auto& builder = function.getBuilder(); const auto& typeName = type->getObjectType()->name().first(); const auto methodID = module.context().getMethodID(CanonicalizeMethodName(methodName)); const auto methodOwner = methodID.isConstructor() ? nullptr : args[0].resolveWithoutBind(function); if (methodName == "__move_to") { const auto moveToPtr = args[1].resolve(function); const auto moveToPosition = args[2].resolve(function); const auto destPtr = builder.CreateInBoundsGEP(moveToPtr, moveToPosition); const auto castedDestPtr = builder.CreatePointerCast(destPtr, genPointerType(module, type)); genMoveStore(function, methodOwner, castedDestPtr, type); return ConstantGenerator(module).getVoidUndef(); } else if (methodName == "create") { return ConstantGenerator(module).getPrimitiveFloat(typeName, 0.0); } else if (methodName == "__setdead" || methodName == "__set_dead") { // Do nothing. return ConstantGenerator(module).getVoidUndef(); } else if (methodName == "__islive" || methodName == "__is_live") { return ConstantGenerator(module).getI1(true); } else if (methodName.starts_with("implicit_cast_") || methodName.starts_with("cast_")) { const auto argType = functionType.parameterTypes().front(); const auto operand = args[0].resolve(function); const auto selfType = genType(module, type); if (isFloatType(module, argType)) { if (methodName.starts_with("implicit_cast_")) { return builder.CreateFPExt(operand, selfType); } else { return builder.CreateFPTrunc(operand, selfType); } } else if (isUnsignedIntegerType(module, argType)) { return builder.CreateUIToFP(operand, selfType); } else if (isSignedIntegerType(module, argType)) { return builder.CreateSIToFP(operand, selfType); } else { llvm_unreachable("Unknown float cast source type."); } } else if (isUnaryOp(methodName)) { const auto zero = ConstantGenerator(module).getPrimitiveFloat(typeName, 0.0); if (methodName == "implicit_cast" || methodName == "cast") { return callCastMethod(function, methodOwner, type, methodName, templateArgs.front().typeRefType(), hintResultValue); } else if (methodName == "implicit_copy" || methodName == "copy" || methodName == "plus") { return methodOwner; } else if (methodName == "minus") { return builder.CreateFNeg(methodOwner); } else if (methodName == "isZero") { return builder.CreateFCmpOEQ(methodOwner, zero); } else if (methodName == "isPositive") { return builder.CreateFCmpOGT(methodOwner, zero); } else if (methodName == "isNegative") { return builder.CreateFCmpOLT(methodOwner, zero); } else if (methodName == "abs") { // Generates: (value < 0) ? -value : value. const auto lessThanZero = builder.CreateFCmpOLT(methodOwner, zero); return builder.CreateSelect(lessThanZero, builder.CreateFNeg(methodOwner), methodOwner); } else if (methodName == "sqrt") { llvm::Type* const intrinsicTypes[] = { methodOwner->getType() }; const auto sqrtIntrinsic = llvm::Intrinsic::getDeclaration(module.getLLVMModulePtr(), llvm::Intrinsic::sqrt, intrinsicTypes); llvm::Value* const sqrtArgs[] = { methodOwner }; return builder.CreateCall(sqrtIntrinsic, sqrtArgs); } else { llvm_unreachable("Unknown primitive unary op."); } } else if (isBinaryOp(methodName)) { const auto operand = args[1].resolveWithoutBind(function); if (methodName == "add") { return builder.CreateFAdd(methodOwner, operand); } else if (methodName == "subtract") { return builder.CreateFSub(methodOwner, operand); } else if (methodName == "multiply") { return builder.CreateFMul(methodOwner, operand); } else if (methodName == "divide") { return builder.CreateFDiv(methodOwner, operand); } else if (methodName == "modulo") { return builder.CreateFRem(methodOwner, operand); } else if (methodName == "equal") { return builder.CreateFCmpOEQ(methodOwner, operand); } else if (methodName == "not_equal") { return builder.CreateFCmpONE(methodOwner, operand); } else if (methodName == "less_than") { return builder.CreateFCmpOLT(methodOwner, operand); } else if (methodName == "less_than_or_equal") { return builder.CreateFCmpOLE(methodOwner, operand); } else if (methodName == "greater_than") { return builder.CreateFCmpOGT(methodOwner, operand); } else if (methodName == "greater_than_or_equal") { return builder.CreateFCmpOGE(methodOwner, operand); } else if (methodName == "compare") { const auto isLessThan = builder.CreateFCmpOLT(methodOwner, operand); const auto isGreaterThan = builder.CreateFCmpOGT(methodOwner, operand); const auto minusOne = ConstantGenerator(module).getI8(-1); const auto zero = ConstantGenerator(module).getI8(0); const auto plusOne = ConstantGenerator(module).getI8(1); return builder.CreateSelect(isLessThan, minusOne, builder.CreateSelect(isGreaterThan, plusOne, zero)); } else { llvm_unreachable("Unknown primitive binary op."); } } else { printf("%s\n", methodName.c_str()); llvm_unreachable("Unknown primitive method."); } }
static int getPriority(Token &tok) { if (isBinaryOp(tok)) return priority[tok.kindOf].left; return -1; }