@Nullable /*package*/ SNode getTypeOf(final SNode node) { ModelAccess.assertLegalRead(); if (node == null) return null; if (myTypeChecker.isGenerationMode()) { TypeCheckingContext context = myTypeChecker.hasPerformanceTracer() ? new TargetTypecheckingContext_Tracer(node, myTypeChecker) : new TargetTypecheckingContext(node, myTypeChecker); try { return context.getTypeOf_generationMode(node); } finally { context.dispose(); } } // now we are not in generation mode final ITypeContextOwner contextOwner = myTypecheckingContextOwner.get(); TypeCheckingContext context = acquireTypecheckingContext(node, contextOwner); if (context == null) { return TypesUtil.createRuntimeErrorType(); } try { return context.getTypeOf(node, myTypeChecker); } finally { releaseTypecheckingContext(node, contextOwner); } }
/** * Start one module after the other and try to compile the input file. Then generate the assembler * file and create this file for jasmin. */ private static void parseCompile(String input, String fileName) throws ParserException, LexerException, IOException { String output; // Init output string StringReader reader = new StringReader(input); // Standard routine to start the parser, lexer, ... PushbackReader r = new PushbackReader(reader, 100); Lexer l = new Lexer(r); Parser parser = new Parser(l); Start start = parser.parse(); // ASTPrinter printer = new ASTPrinter(); // start.apply(printer); TypeChecker typeChecker = new TypeChecker(); // Starting TypeChecker start.apply(typeChecker); CodeGenerator codeGenerator = new CodeGenerator(typeChecker.getSymbolTable()); copySymbolTable( typeChecker, codeGenerator); // To get all the identifiers copied with an index to CodeGen start.apply(codeGenerator); output = createOutput(codeGenerator, fileName); Writer wout = new BufferedWriter( // Write everything to the outputfile.j new OutputStreamWriter(new FileOutputStream(fileName + ".j"), "UTF8")); wout.append(output); wout.close(); }
public TypeCheckingContext createTypeCheckingContext(SNode node) { ModelAccess.assertLegalRead(); if (myTypeChecker.isGenerationMode()) { return new TargetTypecheckingContext(node, myTypeChecker); } else { return new IncrementalTypecheckingContext(node, myTypeChecker); } }
/** Type check the expression. */ public Node typeCheck(TypeChecker tc) throws SemanticException { TypeSystem ts = tc.typeSystem(); if (!ts.isCastValid(expr.type(), castType.type())) { throw new SemanticException( "Cannot cast the expression of type \"" + expr.type() + "\" to type \"" + castType.type() + "\".", position()); } return type(castType.type()); }
/** * Parse an expression * * @param token the initial token. * @return the root of the generated parse subtree. * @throws Exception if an error occurred. */ private ICodeNode parseExpression(Token token) throws Exception { // Parse a simple expression and make the root of its tree // the root node. ICodeNode rootNode = parseSimpleExpression(token); TypeSpec resultType = rootNode != null ? rootNode.getTypeSpec() : Predefined.undefinedType; token = currentToken(); TokenType tokenType = token.getType(); // Look for a relational operator. if (REL_OPS.contains(tokenType)) { // Create a new operator node and adopt the current tree as its first child ICodeNodeType nodeType = REL_OPS_MAP.get(tokenType); ICodeNode opNode = ICodeFactory.createICodeNode(nodeType); opNode.addChild(rootNode); token = nextToken(); // consume the operator // Parse the second simple expression. // The operator node adopts the simple expression's tree as its second child. ICodeNode simExprNode = parseSimpleExpression(token); opNode.addChild(simExprNode); // The operator node becomes the new root node. rootNode = opNode; // Type check: The operands must be comparison compatible. TypeSpec simExprType = simExprNode != null ? simExprNode.getTypeSpec() : Predefined.undefinedType; if (TypeChecker.areComparisionCompatible(resultType, simExprType)) resultType = Predefined.booleanType; else { errorHandler.flag(token, INCOMPATIBLE_TYPES, this); resultType = Predefined.undefinedType; } } if (rootNode != null) rootNode.setTypeSpec(resultType); return rootNode; }
public void typeCheckBody() throws XPathException { Expression exp = compiledFunction.getBody(); Expression exp2 = exp; ExpressionVisitor visitor = makeExpressionVisitor(); try { // We've already done the typecheck of each XPath expression, but it's worth doing again at // this // level because we have more information now. exp2 = visitor.typeCheck(exp, null); if (resultType != null) { RoleLocator role = new RoleLocator(RoleLocator.FUNCTION_RESULT, functionName, 0); role.setErrorCode("XTTE0780"); exp2 = TypeChecker.staticTypeCheck(exp2, resultType, false, role, visitor); } } catch (XPathException err) { err.maybeSetLocation(this); compileError(err); } if (exp2 != exp) { compiledFunction.setBody(exp2); } }
private static boolean checkErrors(Program program, Level nonlinear) { boolean result = true; result = result && hasMainNode(program); result = result && TypeChecker.check(program); result = result && typesUnique(program); result = result && SubrangesNonempty.check(program); result = result && ArraysNonempty.check(program); result = result && constantsUnique(program); result = result && constantsConstant(program); result = result && nodesUnique(program); result = result && NodeDependencyChecker.check(program); result = result && variablesUnique(program); result = result && assignmentsSound(program); result = result && ConstantArrayAccessBounded.check(program); result = result && propertiesUnique(program); result = result && propertiesExist(program); result = result && propertiesBoolean(program); if (nonlinear == Level.ERROR) { result = result && LinearChecker.check(program, nonlinear); } result = result && DivisionChecker.check(program); return result; }
/** Type check the statement. */ public Node typeCheck(TypeChecker tc) throws SemanticException { TypeSystem ts = tc.typeSystem(); // Check that all initializers have the same type. // This should be enforced by the parser, but check again here, // just to be sure. Type t = null; for (Iterator i = inits.iterator(); i.hasNext(); ) { ForInit s = (ForInit) i.next(); if (s instanceof LocalDecl) { LocalDecl d = (LocalDecl) s; Type dt = d.type().type(); if (t == null) { t = dt; } else if (!t.equals(dt)) { throw new InternalCompilerError( "Local variable " + "declarations in a for loop initializer must all " + "be the same type, in this case " + t + ", not " + dt + ".", d.position()); } } } if (cond != null && !ts.isImplicitCastValid(cond.type(), ts.Boolean())) { throw new SemanticException( "The condition of a for statement must have boolean type.", cond.position()); } return this; }
/** * Copy SymbolTable from the TypeChecker to the CodeGenerator and give it a new index (not * necessary to know the types any more - they are all correct!) */ private static void copySymbolTable(TypeChecker typeChecker, CodeGenerator codeGenerator) { int i = typeChecker.getSymbolTable().size(); for (String id : typeChecker.getSymbolTable().keySet()) codeGenerator.getSymbolTable().put(id, i--); }
private int computeLabel(ASTree expr) throws CompileError { doTypeCheck(expr); expr = TypeChecker.stripPlusExpr(expr); if (expr instanceof IntConst) return (int) ((IntConst) expr).get(); else throw new CompileError("bad case label"); }
/** Type check the expression. */ public Node typeCheck(TypeChecker tc) throws SemanticException { return type(tc.typeSystem().Boolean()); }
/** * Compile: this registers the template with the rule manager, and ensures space is available for * local variables */ public Expression compile(Executable exec) throws XPathException { Expression block = compileSequenceConstructor(exec, iterateAxis(Axis.CHILD), true); if (block == null) { block = Literal.makeEmptySequence(); } compiledTemplate.setMatchPattern(match); compiledTemplate.setBody(block); compiledTemplate.setStackFrameMap(stackFrameMap); compiledTemplate.setExecutable(getExecutable()); compiledTemplate.setSystemId(getSystemId()); compiledTemplate.setLineNumber(getLineNumber()); compiledTemplate.setHasRequiredParams(hasRequiredParams); compiledTemplate.setRequiredType(requiredType); Expression exp = null; try { exp = makeExpressionVisitor().simplify(block); } catch (XPathException e) { compileError(e); } try { if (requiredType != null) { RoleLocator role = new RoleLocator(RoleLocator.TEMPLATE_RESULT, diagnosticId, 0); // role.setSourceLocator(new ExpressionLocation(this)); role.setErrorCode("XTTE0505"); exp = TypeChecker.staticTypeCheck(exp, requiredType, false, role, makeExpressionVisitor()); } } catch (XPathException err) { compileError(err); } compiledTemplate.setBody(exp); compiledTemplate.init(getObjectName(), getPrecedence(), getMinImportPrecedence()); if (getConfiguration().isCompileWithTracing()) { TraceWrapper trace = new TraceInstruction(exp, this); trace.setLocationId(allocateLocationId(getSystemId(), getLineNumber())); trace.setContainer(compiledTemplate); exp = trace; compiledTemplate.setBody(exp); } ItemType contextItemType = Type.ITEM_TYPE; if (getObjectName() == null) { // the template can't be called by name, so the context item must match the match pattern contextItemType = match.getNodeTest(); } ExpressionVisitor visitor = makeExpressionVisitor(); try { // We've already done the typecheck of each XPath expression, but it's worth doing again at // this // level because we have more information now. Expression exp2 = visitor.typeCheck(exp, contextItemType); exp2 = visitor.optimize(exp2, contextItemType); if (exp != exp2) { compiledTemplate.setBody(exp2); exp = exp2; } } catch (XPathException e) { compileError(e); } // Try to extract new global variables from the body of the function // ExpressionPresenter presenter = ExpressionPresenter.make(getConfiguration()); // exp.explain(presenter); // presenter.close(); if (!getConfiguration().isCompileWithTracing()) { Expression exp2 = getConfiguration().getOptimizer().promoteExpressionsToGlobal(exp, visitor); if (exp != exp2) { compiledTemplate.setBody(exp2); exp = exp2; } } allocateSlots(exp); if (match != null) { RuleManager mgr = getPrincipalStylesheet().getRuleManager(); for (int i = 0; i < modeNames.length; i++) { StructuredQName nc = modeNames[i]; Mode mode = mgr.getMode(nc, true); if (prioritySpecified) { mgr.setHandler(match, compiledTemplate, mode, getPrecedence(), priority); } else { mgr.setHandler(match, compiledTemplate, mode, getPrecedence()); } } allocatePatternSlots(match, getSlotManager()); } if (isExplaining()) { System.err.println( "Optimized expression tree for template at line " + getLineNumber() + " in " + getSystemId() + ':'); exp.explain(System.err); } return null; }
/** * Parse a factor. * * @param token the initial token. * @return the root of the generated parse subtree. * @throws Exception if an error occurred. */ private ICodeNode parseFactor(Token token) throws Exception { TokenType tokenType = token.getType(); ICodeNode rootNode = null; switch ((PascalTokenType) tokenType) { case IDENTIFIER: { return parseIdentifier(token); } case INTEGER: { // Create an INTEGER_CONSTANT node as the root node rootNode = ICodeFactory.createICodeNode(INTEGER_CONSTANT); rootNode.setAttribute(VALUE, token.getValue()); token = nextToken(); // consume the number rootNode.setTypeSpec(Predefined.integerType); break; } case REAL: { // Create an REAL_CONSTANT node as the root node. rootNode = ICodeFactory.createICodeNode(REAL_CONSTANT); rootNode.setAttribute(VALUE, token.getValue()); token = nextToken(); // consume the number rootNode.setTypeSpec(Predefined.realType); break; } case STRING: { String value = (String) token.getValue(); // Create a STRING_CONSTANT node as the root node. rootNode = ICodeFactory.createICodeNode(STRING_CONSTANT); rootNode.setAttribute(VALUE, value); TypeSpec resultType = value.length() == 1 ? Predefined.charType : TypeFactory.createStringType(value); token = nextToken(); // consume the string rootNode.setTypeSpec(resultType); break; } case NOT: { token = nextToken(); // consume the NOT // Create a NOT node as the root node. rootNode = ICodeFactory.createICodeNode(ICodeNodeTypeImpl.NOT); // Parse the factor. The NOT node adopts the factor node as its child. ICodeNode factorNode = parseFactor(token); rootNode.addChild(factorNode); // Type check: the factor must be boolean. TypeSpec factorType = factorNode != null ? factorNode.getTypeSpec() : Predefined.undefinedType; if (!TypeChecker.isBoolean(factorType)) errorHandler.flag(token, INCOMPATIBLE_TYPES, this); rootNode.setTypeSpec(Predefined.booleanType); break; } case LEFT_PAREN: { token = nextToken(); // consume the ( // Parse an expression and make its node the root node. rootNode = parseExpression(token); TypeSpec resultType = rootNode != null ? rootNode.getTypeSpec() : Predefined.undefinedType; // Look for the matching ) token. token = currentToken(); if (token.getType() == RIGHT_PAREN) token = nextToken(); // consume the ) else errorHandler.flag(token, MISSING_RIGHT_PAREN, this); rootNode.setTypeSpec(resultType); break; } default: { errorHandler.flag(token, UNEXPECTED_TOKEN, this); break; } } return rootNode; }
/** * Parse a term. * * @param token the initial token. * @return the root of the generated parse subtree. * @throws Exception if an error occurred. */ private ICodeNode parseTerm(Token token) throws Exception { // Parse a factor and makes its node the root node. ICodeNode rootNode = parseFactor(token); TypeSpec resultType = rootNode != null ? rootNode.getTypeSpec() : Predefined.undefinedType; token = currentToken(); TokenType tokenType = token.getType(); // Loop over multiplicative operators. while (MULT_OPS.contains(tokenType)) { TokenType operator = tokenType; // Create a new operator node and adopt the current tree as its first child. ICodeNodeType nodeType = MULT_OPS_OPS_MAP.get(operator); ICodeNode opNode = ICodeFactory.createICodeNode(nodeType); opNode.addChild(rootNode); token = nextToken(); // consume the operator // Parse another factor. // The operator node adopts the term's tree as its secomd child. ICodeNode factorNode = parseFactor(token); opNode.addChild(factorNode); TypeSpec factorType = factorNode != null ? factorNode.getTypeSpec() : Predefined.undefinedType; // The operator node becomes the new root node. rootNode = opNode; // Determine the result type. switch ((PascalTokenType) operator) { case STAR: { // Both operands integer ==> integer result. if (TypeChecker.areBothInteger(resultType, factorType)) { resultType = Predefined.integerType; } // Both real operands or one real and one integer operand // ==> real result. else if (TypeChecker.isAtLeastOneReal(resultType, factorType)) { resultType = Predefined.realType; } else { errorHandler.flag(token, INCOMPATIBLE_TYPES, this); } break; } case SLASH: { // All integer and real operand combinations // ==> real result. if (TypeChecker.areBothInteger(resultType, factorType) || TypeChecker.isAtLeastOneReal(resultType, factorType)) { resultType = Predefined.realType; } else { errorHandler.flag(token, INCOMPATIBLE_TYPES, this); } break; } case DIV: case MOD: { // Both operands integer ==> integer result. if (TypeChecker.areBothInteger(resultType, factorType)) { resultType = Predefined.integerType; } else { errorHandler.flag(token, INCOMPATIBLE_TYPES, this); } break; } case AND: { // Both operands boolean ==> boolean result. if (TypeChecker.areBothBoolean(resultType, factorType)) { resultType = Predefined.booleanType; } else { errorHandler.flag(token, INCOMPATIBLE_TYPES, this); } break; } } // The operator node becomes the new root node. rootNode.setTypeSpec(resultType); token = currentToken(); tokenType = token.getType(); } return rootNode; }
/** * Parse a simple expression. * * @param token the initial token. * @return the root of the generated parse subtree. * @throws Exception if an error occurred. */ private ICodeNode parseSimpleExpression(Token token) throws Exception { Token signToken = null; TokenType signType = null; // type of leading sign (if any) // Look for a leading + or - sign TokenType tokenType = token.getType(); if ((tokenType == PLUS) || (tokenType == MINUS)) { signType = tokenType; signToken = token; token = nextToken(); // consume the + or - } // Parse a term and make the root of its tree the root node. ICodeNode rootNode = parseTerm(token); TypeSpec resultType = rootNode != null ? rootNode.getTypeSpec() : Predefined.undefinedType; // Type check: Leading sign. if ((signType != null) && (!TypeChecker.isIntegerOrReal(resultType))) errorHandler.flag(signToken, INCOMPATIBLE_TYPES, this); // Was there a leading - sign? if (signType == MINUS) { // Create a NEGATE node and adopt the current tree as its child. // The NEGATE node becomes the new root node. ICodeNode negateNode = ICodeFactory.createICodeNode(NEGATE); negateNode.addChild(rootNode); negateNode.setTypeSpec(rootNode.getTypeSpec()); rootNode = negateNode; } token = currentToken(); tokenType = token.getType(); // Loop over additive operators. while (ADD_OPS.contains(tokenType)) { TokenType operator = tokenType; // Create a new operator node and adopt the current tree as its first child. ICodeNodeType nodeType = ADD_OPS_OPS_MAP.get(operator); ICodeNode opNode = ICodeFactory.createICodeNode(nodeType); opNode.addChild(rootNode); token = nextToken(); // consume the operator // Parse another term. // The operator node adopts the term's tree as its second child. ICodeNode termNode = parseTerm(token); opNode.addChild(termNode); TypeSpec termType = termNode != null ? termNode.getTypeSpec() : Predefined.undefinedType; // The operator node becomes the new root node. rootNode = opNode; switch ((PascalTokenType) operator) { case PLUS: case MINUS: { // Both operands integer => integer result. if (TypeChecker.areBothInteger(resultType, termType)) resultType = Predefined.integerType; // Both real operands or one real and one integer operand => real result. else if (TypeChecker.isAtLeastOneReal(resultType, termType)) resultType = Predefined.realType; else errorHandler.flag(token, INCOMPATIBLE_TYPES, this); break; } case OR: { // Both operands boolean ==> boolean result. if (TypeChecker.areBothBoolean(resultType, termType)) resultType = Predefined.booleanType; else errorHandler.flag(token, INCOMPATIBLE_TYPES, this); break; } } rootNode.setTypeSpec(resultType); token = currentToken(); tokenType = token.getType(); } return rootNode; }