Mercurial > hg > truffle
diff graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/SLNodeFactory.java @ 13821:b16ec83edc73
Documentation and more refactoring of Simple Language
author | Christian Wimmer <christian.wimmer@oracle.com> |
---|---|
date | Wed, 29 Jan 2014 20:45:43 -0800 |
parents | 739194d1e813 |
children | 64c77f0577bb |
line wrap: on
line diff
--- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/SLNodeFactory.java Wed Jan 29 20:43:28 2014 -0800 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/SLNodeFactory.java Wed Jan 29 20:45:43 2014 -0800 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,6 +27,7 @@ import com.oracle.truffle.api.*; import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.impl.*; import com.oracle.truffle.api.nodes.*; import com.oracle.truffle.sl.nodes.*; import com.oracle.truffle.sl.nodes.call.*; @@ -53,50 +54,56 @@ /* State while parsing a source unit. */ private final SLContext context; private final Source source; - private final Parser parser; /* State while parsing a function. */ private String functionName; + private int parameterCount; private FrameDescriptor frameDescriptor; private List<SLStatementNode> methodNodes; /* State while parsing a block. */ private LexicalScope lexicalScope; - public SLNodeFactory(SLContext context, Source source, Parser parser) { + public SLNodeFactory(SLContext context, Source source) { this.context = context; this.source = source; - this.parser = parser; } - public void startFunction(String name, List<String> parameters) { + public void startFunction(Token nameToken) { assert functionName == null; + assert parameterCount == 0; assert frameDescriptor == null; assert lexicalScope == null; - functionName = name; + functionName = nameToken.val; frameDescriptor = new FrameDescriptor(); + methodNodes = new ArrayList<>(); startBlock(); + } + public void addFormalParameter(Token nameToken) { /* * Method parameters are assigned to local variables at the beginning of the method. This * ensures that accesses to parameters are specialized the same way as local variables are * specialized. */ - methodNodes = new ArrayList<>(parameters.size()); - for (int i = 0; i < parameters.size(); i++) { - methodNodes.add(createAssignment(parameters.get(i), new SLReadArgumentNode(i))); - } + SLReadArgumentNode readArg = assignSource(nameToken, new SLReadArgumentNode(parameterCount)); + methodNodes.add(createAssignment(nameToken, readArg)); + parameterCount++; } - public void finishFunction(SLStatementNode body) { - methodNodes.add(body); + public void finishFunction(SLStatementNode bodyNode) { + methodNodes.add(bodyNode); SLStatementNode methodBlock = finishBlock(methodNodes); assert lexicalScope == null : "Wrong scoping of blocks in parser"; - context.getFunctionRegistry().register(functionName, SLRootNode.createFunction(functionName, frameDescriptor, methodBlock)); + SLFunctionBodyNode functionBodyNode = new SLFunctionBodyNode(methodBlock); + SLRootNode rootNode = new SLRootNode(frameDescriptor, functionBodyNode, functionName); + + context.getFunctionRegistry().register(functionName, rootNode); functionName = null; + parameterCount = 0; frameDescriptor = null; lexicalScope = null; } @@ -105,123 +112,131 @@ lexicalScope = new LexicalScope(lexicalScope); } - public SLStatementNode finishBlock(List<SLStatementNode> statements) { + public SLStatementNode finishBlock(List<SLStatementNode> bodyNodes) { lexicalScope = lexicalScope.outer; - List<SLStatementNode> flattened = new ArrayList<>(statements.size()); - flattenBlocks(statements, flattened); - if (flattened.size() == 1) { - return flattened.get(0); + List<SLStatementNode> flattenedNodes = new ArrayList<>(bodyNodes.size()); + flattenBlocks(bodyNodes, flattenedNodes); + if (flattenedNodes.size() == 1) { + /* A block containing one other node is unnecessary, we can just that other node. */ + return flattenedNodes.get(0); } else { - return assignSource(new SLBlockNode(flattened.toArray(new SLStatementNode[flattened.size()]))); + return new SLBlockNode(flattenedNodes.toArray(new SLStatementNode[flattenedNodes.size()])); } } - private void flattenBlocks(Iterable<? extends Node> statements, List<SLStatementNode> flattened) { - for (Node statement : statements) { - if (statement instanceof SLBlockNode) { - flattenBlocks(statement.getChildren(), flattened); + private void flattenBlocks(Iterable<? extends Node> bodyNodes, List<SLStatementNode> flattenedNodes) { + for (Node n : bodyNodes) { + if (n instanceof SLBlockNode) { + flattenBlocks(n.getChildren(), flattenedNodes); } else { - flattened.add((SLStatementNode) statement); + flattenedNodes.add((SLStatementNode) n); } } } - private <T extends Node> T assignSource(T node) { - assert functionName != null; - node.assignSourceSection(ParserUtils.createSourceSection(source, functionName, parser)); - return node; + public SLStatementNode createBreak(Token t) { + return assignSource(t, new SLBreakNode()); + } + + public SLStatementNode createContinue(Token t) { + return assignSource(t, new SLContinueNode()); } - public SLExpressionNode createAssignment(String name, SLExpressionNode value) { - FrameSlot frameSlot = frameDescriptor.findOrAddFrameSlot(name); - lexicalScope.locals.put(name, frameSlot); - return assignSource(WriteLocalNodeFactory.create(frameSlot, value)); + public SLStatementNode createWhile(Token t, SLExpressionNode conditionNode, SLStatementNode bodyNode) { + return assignSource(t, new SLWhileNode(conditionNode, bodyNode)); + } + + public SLStatementNode createIf(Token t, SLExpressionNode conditionNode, SLStatementNode thenPartNode, SLStatementNode elsePartNode) { + return assignSource(t, new SLIfNode(conditionNode, thenPartNode, elsePartNode)); + } + + public SLStatementNode createReturn(Token t, SLExpressionNode valueNode) { + return assignSource(t, new SLReturnNode(valueNode)); } - public SLExpressionNode createRead(String name) { - FrameSlot frameSlot = lexicalScope.locals.get(name); - if (frameSlot != null) { - /* Read of a local variable. */ - return assignSource(ReadLocalNodeFactory.create(frameSlot)); - } else { - /* Read of a global name. In our language, the only global names are functions. */ - return new SLFunctionLiteralNode(context.getFunctionRegistry().lookup(name)); - } - } - - public SLExpressionNode createNumericLiteral(String value) { - try { - return assignSource(new SLLongLiteralNode(Long.parseLong(value))); - } catch (NumberFormatException ex) { - return assignSource(new SLBigIntegerLiteralNode(new BigInteger(value))); + public SLExpressionNode createBinary(Token opToken, SLExpressionNode leftNode, SLExpressionNode rightNode) { + switch (opToken.val) { + case "+": + return assignSource(opToken, SLAddNodeFactory.create(leftNode, rightNode)); + case "*": + return assignSource(opToken, SLMulNodeFactory.create(leftNode, rightNode)); + case "/": + return assignSource(opToken, SLDivNodeFactory.create(leftNode, rightNode)); + case "-": + return assignSource(opToken, SLSubNodeFactory.create(leftNode, rightNode)); + case "<": + return assignSource(opToken, SLLessThanNodeFactory.create(leftNode, rightNode)); + case "<=": + return assignSource(opToken, SLLessOrEqualNodeFactory.create(leftNode, rightNode)); + case ">": + return assignSource(opToken, SLLogicalNotNodeFactory.create(assignSource(opToken, SLLessOrEqualNodeFactory.create(leftNode, rightNode)))); + case ">=": + return assignSource(opToken, SLLogicalNotNodeFactory.create(assignSource(opToken, SLLessThanNodeFactory.create(leftNode, rightNode)))); + case "==": + return assignSource(opToken, SLEqualNodeFactory.create(leftNode, rightNode)); + case "!=": + return assignSource(opToken, SLLogicalNotNodeFactory.create(assignSource(opToken, SLEqualNodeFactory.create(leftNode, rightNode)))); + case "&&": + return assignSource(opToken, SLLogicalAndNodeFactory.create(leftNode, rightNode)); + case "||": + return assignSource(opToken, SLLogicalOrNodeFactory.create(leftNode, rightNode)); + default: + throw new RuntimeException("unexpected operation: " + opToken.val); } } - public SLExpressionNode createStringLiteral(String value) { - return assignSource(new SLStringLiteralNode(value)); - } - - public SLStatementNode createWhile(SLExpressionNode condition, SLStatementNode body) { - return assignSource(new SLWhileNode(condition, body)); + public SLExpressionNode createCall(Token nameToken, List<SLExpressionNode> parameterNodes) { + SLExpressionNode functionNode = createRead(nameToken); + return assignSource(nameToken, SLCallNode.create(functionNode, parameterNodes.toArray(new SLExpressionNode[parameterNodes.size()]))); } - public SLStatementNode createBreak() { - return assignSource(new SLBreakNode()); + public SLExpressionNode createAssignment(Token nameToken, SLExpressionNode valueNode) { + FrameSlot frameSlot = frameDescriptor.findOrAddFrameSlot(nameToken.val); + lexicalScope.locals.put(nameToken.val, frameSlot); + return assignSource(nameToken, SLWriteLocalVariableNodeFactory.create(valueNode, frameSlot)); } - public SLStatementNode createContinue() { - return assignSource(new SLContinueNode()); - } - - public SLExpressionNode createCall(SLExpressionNode function, List<SLExpressionNode> parameters) { - return assignSource(SLCallNode.create(function, parameters.toArray(new SLExpressionNode[parameters.size()]))); + public SLExpressionNode createRead(Token nameToken) { + FrameSlot frameSlot = lexicalScope.locals.get(nameToken.val); + if (frameSlot != null) { + /* Read of a local variable. */ + return assignSource(nameToken, SLReadLocalVariableNodeFactory.create(frameSlot)); + } else { + /* Read of a global name. In our language, the only global names are functions. */ + return assignSource(nameToken, new SLFunctionLiteralNode(context.getFunctionRegistry().lookup(nameToken.val))); + } } - public SLExpressionNode createBinary(String operation, SLExpressionNode left, SLExpressionNode right) { - SLExpressionNode binary; - switch (operation) { - case "+": - binary = SLAddNodeFactory.create(left, right); - break; - case "*": - binary = SLMulNodeFactory.create(left, right); - break; - case "/": - binary = SLDivNodeFactory.create(left, right); - break; - case "-": - binary = SLSubNodeFactory.create(left, right); - break; - case "<": - binary = SLLessThanNodeFactory.create(left, right); - break; - case "<=": - binary = SLLessOrEqualNodeFactory.create(left, right); - break; - case "==": - binary = SLEqualNodeFactory.create(left, right); - break; - case "!=": - binary = SLNotEqualNodeFactory.create(left, right); - break; - case "&&": - binary = SLLogicalAndNodeFactory.create(left, right); - break; - case "||": - binary = SLLogicalOrNodeFactory.create(left, right); - break; - default: - throw new RuntimeException("unexpected operation: " + operation); - } - return assignSource(binary); + public SLExpressionNode createStringLiteral(Token literalToken) { + /* Remove the trailing and ending " */ + String literal = literalToken.val; + assert literal.length() >= 2 && literal.startsWith("\"") && literal.endsWith("\""); + literal = literal.substring(1, literal.length() - 1); + + return assignSource(literalToken, new SLStringLiteralNode(literal)); } - public SLStatementNode createReturn(SLExpressionNode value) { - return assignSource(new SLReturnNode(value)); + public SLExpressionNode createNumericLiteral(Token literalToken) { + try { + /* Try if the literal is small enough to fit into a long value. */ + return assignSource(literalToken, new SLLongLiteralNode(Long.parseLong(literalToken.val))); + } catch (NumberFormatException ex) { + /* Overflow of long value, so fall back to BigInteger. */ + return assignSource(literalToken, new SLBigIntegerLiteralNode(new BigInteger(literalToken.val))); + } } - public SLStatementNode createIf(SLExpressionNode condition, SLStatementNode then, SLStatementNode elseNode) { - return assignSource(new SLIfNode(condition, then, elseNode)); + private <T extends Node> T assignSource(Token t, T node) { + assert functionName != null; + assert t != null; + + int startLine = t.line; + int startColumn = t.col; + int charLength = t.val.length(); + SourceSection sourceSection = new DefaultSourceSection(source, functionName, startLine, startColumn, 0, charLength); + + node.assignSourceSection(sourceSection); + return node; } }