# HG changeset patch # User Christian Humer # Date 1361292070 -3600 # Node ID 268d3e74191e8365dded168bf1a3cb755a9bf48b # Parent 698cd036a1cad4a6c536309a37a106bf7a673b24# Parent 8959b331ef3e73144a0b48009fd4f7824f8a4058 Merge. diff -r 8959b331ef3e -r 268d3e74191e graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/TruffleTypes.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/TruffleTypes.java Tue Feb 19 16:03:11 2013 +0100 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/TruffleTypes.java Tue Feb 19 17:41:10 2013 +0100 @@ -28,6 +28,7 @@ import javax.lang.model.type.*; import com.oracle.truffle.api.frame.*; +import com.oracle.truffle.api.intrinsics.*; import com.oracle.truffle.api.nodes.*; import com.oracle.truffle.api.nodes.Node.Child; import com.oracle.truffle.api.nodes.Node.Children; @@ -44,6 +45,7 @@ private final TypeMirror stableAnnotation; private final TypeMirror contentStableAnnotation; private final TypeMirror typeConversion; + private final TypeMirror truffleIntrinsics; private final List errors = new ArrayList<>(); @@ -55,6 +57,7 @@ stableAnnotation = getRequired(context, Child.class); contentStableAnnotation = getRequired(context, Children.class); typeConversion = getRequired(context, TypeConversion.class); + truffleIntrinsics = getRequired(context, TruffleIntrinsics.class); } public boolean verify(ProcessorContext context, Element element, AnnotationMirror mirror) { @@ -77,6 +80,10 @@ return type; } + public TypeMirror getTruffleIntrinsics() { + return truffleIntrinsics; + } + public TypeMirror getTypeConversion() { return typeConversion; } diff -r 8959b331ef3e -r 268d3e74191e graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeExecutableElement.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeExecutableElement.java Tue Feb 19 16:03:11 2013 +0100 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeExecutableElement.java Tue Feb 19 17:41:10 2013 +0100 @@ -114,7 +114,7 @@ } public CodeTreeBuilder createBuilder() { - CodeTreeBuilder builder = new CodeTreeBuilder(); + CodeTreeBuilder builder = new CodeTreeBuilder(null); this.bodyTree = builder.getTree(); this.bodyTree.setEnclosingElement(this); this.body = null; diff -r 8959b331ef3e -r 268d3e74191e graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeTreeBuilder.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeTreeBuilder.java Tue Feb 19 16:03:11 2013 +0100 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeTreeBuilder.java Tue Feb 19 17:41:10 2013 +0100 @@ -33,17 +33,25 @@ public class CodeTreeBuilder { + private final CodeTreeBuilder parent; + private BuilderCodeTree currentElement; private final BuilderCodeTree root; - public CodeTreeBuilder() { + private int treeCount; + + public CodeTreeBuilder(CodeTreeBuilder parent) { this.root = new BuilderCodeTree(GROUP, null, null); this.currentElement = root; + this.parent = parent; } - public CodeTreeBuilder(CodeTree tree) { - this.root = (BuilderCodeTree) tree; - this.currentElement = root; + public int getTreeCount() { + return treeCount; + } + + public boolean isEmpty() { + return treeCount == 0; } public CodeTreeBuilder statement(String statement) { @@ -55,11 +63,11 @@ } public static CodeTreeBuilder createBuilder() { - return new CodeTreeBuilder(); + return new CodeTreeBuilder(null); } public static CodeTree singleString(String s) { - return new CodeTreeBuilder().string(s).getTree(); + return new CodeTreeBuilder(null).string(s).getTree(); } private CodeTreeBuilder push(CodeTreeKind kind) { @@ -89,11 +97,14 @@ currentElement = tree; break; } + treeCount++; return this; } private void clearLast(CodeTreeKind kind) { - clearLastRec(kind, currentElement.getEnclosedElements()); + if (clearLastRec(kind, currentElement.getEnclosedElements())) { + treeCount--; + } } public CodeTreeBuilder startStatement() { @@ -358,6 +369,13 @@ return push(CodeTreeKind.INDENT); } + public CodeTreeBuilder end(int times) { + for (int i = 0; i < times; i++) { + end(); + } + return this; + } + public CodeTreeBuilder end() { BuilderCodeTree tree = currentElement; EndCallback callback = tree.getAtEndListener(); @@ -372,9 +390,9 @@ } private void toParent() { - Element parent = currentElement.getEnclosingElement(); + Element parentElement = currentElement.getEnclosingElement(); if (currentElement != root) { - this.currentElement = (BuilderCodeTree) parent; + this.currentElement = (BuilderCodeTree) parentElement; } else { this.currentElement = root; } @@ -433,7 +451,7 @@ } public CodeTreeBuilder create() { - return new CodeTreeBuilder(); + return new CodeTreeBuilder(null); } public CodeTreeBuilder type(TypeMirror type) { @@ -496,7 +514,11 @@ while (element != null && (element.getKind() != ElementKind.METHOD)) { element = element.getEnclosingElement(); } - return element != null ? (ExecutableElement) element : null; + ExecutableElement found = element != null ? (ExecutableElement) element : null; + if (found == null && parent != null) { + found = parent.findMethod(); + } + return found; } public CodeTreeBuilder returnTrue() { diff -r 8959b331ef3e -r 268d3e74191e graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeVariableElement.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeVariableElement.java Tue Feb 19 16:03:11 2013 +0100 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/ast/CodeVariableElement.java Tue Feb 19 17:41:10 2013 +0100 @@ -58,7 +58,7 @@ } public CodeTreeBuilder createInitBuilder() { - CodeTreeBuilder builder = new CodeTreeBuilder(); + CodeTreeBuilder builder = new CodeTreeBuilder(null); init = builder.getTree(); init.setEnclosingElement(this); return builder; diff -r 8959b331ef3e -r 268d3e74191e graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/codewriter/AbstractCodeWriter.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/codewriter/AbstractCodeWriter.java Tue Feb 19 16:03:11 2013 +0100 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/codewriter/AbstractCodeWriter.java Tue Feb 19 17:41:10 2013 +0100 @@ -36,9 +36,16 @@ public abstract class AbstractCodeWriter extends CodeElementScanner { + private static final int LINE_LENGTH = 200; + private static final int LINE_WRAP_INDENTS = 3; + private static final String IDENT_STRING = " "; + private static final String LN = "\n"; /* unix style */ + protected Writer writer; private int indent; private boolean newLine; + private int lineLength; + private boolean lineWrapping = false; private OrganizedImports imports; @@ -56,8 +63,7 @@ Writer w = null; try { imports = OrganizedImports.organize(e); - - w = createWriter(e); + w = new TrimTrailingSpaceWriter(createWriter(e)); writer = w; writeRootClass(e); } catch (IOException ex) { @@ -145,7 +151,7 @@ write(" {").writeLn(); writeEmptyLn(); - indent(); + indent(1); List staticFields = getStaticFields(e); List instanceFields = getInstanceFields(e); @@ -191,7 +197,7 @@ clazz.accept(this, null); } - dedent(); + dedent(1); write("}"); writeEmptyLn(); } @@ -474,9 +480,9 @@ writeLn(";"); } else if (e.getBodyTree() != null) { writeLn(" {"); - indent(); + indent(1); e.getBodyTree().acceptCodeElementScanner(this, p); - dedent(); + dedent(1); writeLn("}"); } else if (e.getBody() != null) { write(" {"); @@ -509,11 +515,11 @@ } break; case INDENT: - indent(); + indent(1); for (CodeTree tree : e.getEnclosedElements()) { tree.acceptCodeElementScanner(this, p); } - dedent(); + dedent(1); break; case NEW_LINE: writeLn(); @@ -565,25 +571,28 @@ } } - private static final String LN = "\n"; - - protected void indent() { - indent++; + protected void indent(int count) { + indent += count; } - protected void dedent() { - indent--; + protected void dedent(int count) { + indent -= count; } protected void writeLn() { - write(LN); - newLine = true; + writeLn(""); } protected void writeLn(String text) { write(text); write(LN); + lineLength = 0; newLine = true; + if (lineWrapping) { + dedent(LINE_WRAP_INDENTS); + lineWrapping = false; + } + lineWrapping = false; } protected void writeEmptyLn() { @@ -596,10 +605,23 @@ private AbstractCodeWriter write(String m) { try { + lineLength += m.length(); if (newLine && m != LN) { writeIndent(); newLine = false; } + if (lineLength > LINE_LENGTH && m.length() > 0) { + char firstChar = m.charAt(0); + if (Character.isAlphabetic(firstChar)) { + if (!lineWrapping) { + indent(LINE_WRAP_INDENTS); + } + lineWrapping = true; + lineLength = 0; + write(LN); + writeIndent(); + } + } writer.write(m); } catch (IOException e) { throw new RuntimeException(e); @@ -609,7 +631,57 @@ private void writeIndent() throws IOException { for (int i = 0; i < indent; i++) { - writer.write(" "); + lineLength += IDENT_STRING.length(); + writer.write(IDENT_STRING); } } + + private static class TrimTrailingSpaceWriter extends Writer { + + private final Writer delegate; + private final StringBuilder buffer = new StringBuilder(); + + public TrimTrailingSpaceWriter(Writer delegate) { + this.delegate = delegate; + } + + @Override + public void close() throws IOException { + this.delegate.close(); + } + + @Override + public void flush() throws IOException { + this.delegate.flush(); + } + + @Override + public void write(char[] cbuf, int off, int len) throws IOException { + buffer.append(cbuf, off, len); + int newLinePoint = buffer.indexOf(LN); + + if (newLinePoint != -1) { + String lhs = trimTrailing(buffer.substring(0, newLinePoint)); + delegate.write(lhs); + delegate.write(LN); + buffer.delete(0, newLinePoint + 1); + } + } + + private static String trimTrailing(String s) { + int cut = 0; + for (int i = s.length() - 1; i >= 0; i--) { + if (Character.isWhitespace(s.charAt(i))) { + cut++; + } else { + break; + } + } + if (cut > 0) { + return s.substring(0, s.length() - cut); + } + return s; + } + } + } diff -r 8959b331ef3e -r 268d3e74191e graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeCodeGenerator.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeCodeGenerator.java Tue Feb 19 16:03:11 2013 +0100 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeCodeGenerator.java Tue Feb 19 17:41:10 2013 +0100 @@ -69,7 +69,8 @@ private static String specializationId(SpecializationData specialization) { String name = ""; - if (specialization.getNode().getSpecializations().length > 1) { + NodeData node = specialization.getNode(); + if (node.getSpecializations().length > 1) { name = specialization.getMethodName(); if (name.startsWith("do")) { name = name.substring(2); @@ -82,8 +83,8 @@ return field.getName() + "Value"; } - private static String valueName(TemplateMethod method, ActualParameter param) { - NodeData node = (NodeData) method.getTemplate(); + private static String valueName(ActualParameter param) { + NodeData node = (NodeData) param.getMethod().getTemplate(); NodeFieldData field = node.findField(param.getSpecification().getName()); if (field != null) { return valueName(field); @@ -92,6 +93,14 @@ } } + private static String castValueName(ActualParameter parameter) { + return valueName(parameter) + "Cast"; + } + + private static String castValueName(NodeFieldData field) { + return valueName(field) + "Cast"; + } + private void addValueParameters(CodeExecutableElement method, TemplateMethod specialization, boolean forceFrame) { if (forceFrame) { method.addParameter(new CodeVariableElement(getContext().getTruffleTypes().getFrame(), "frame")); @@ -101,7 +110,7 @@ if (forceFrame && spec.getName().equals("frame")) { continue; } - method.addParameter(new CodeVariableElement(parameter.getActualType(), valueName(specialization, parameter))); + method.addParameter(new CodeVariableElement(parameter.getActualType(), valueName(parameter))); } } @@ -118,21 +127,28 @@ if (unexpectedValueName != null && spec.getName().equals(unexpectedValueName)) { builder.string("ex.getResult()"); } else { - builder.string(valueName(specialization, parameter)); + builder.string(valueName(parameter)); } } } - private static void addValueParameterNamesWithCasts(ProcessorContext context, CodeTreeBuilder body, SpecializationData specialization) { - for (ActualParameter param : specialization.getParameters()) { - TypeData typeData = param.getActualTypeData(specialization.getNode().getTypeSystem()); - if (typeData == null || typeData.isGeneric()) { - body.string(valueName(specialization, param)); + private static void addValueParameterNamesWithCasts(CodeTreeBuilder body, SpecializationData valueSpecialization, SpecializationData targetSpecialization) { + NodeData node = targetSpecialization.getNode(); + TypeSystemData typeSystem = node.getTypeSystem(); + + for (ActualParameter targetParameter : targetSpecialization.getParameters()) { + ActualParameter valueParameter = valueSpecialization.findParameter(targetParameter.getSpecification().getName()); + TypeData targetType = targetParameter.getActualTypeData(typeSystem); + + TypeData valueType = null; + if (valueParameter != null) { + valueType = valueParameter.getActualTypeData(typeSystem); + } + + if (targetType == null || targetType.isGeneric() || (valueType != null && valueType.equalsType(targetType))) { + body.string(valueName(targetParameter)); } else { - String methodName = TypeSystemCodeGenerator.asTypeMethodName(typeData); - startCallTypeSystemMethod(context, body, specialization.getNode(), methodName); - body.string(valueName(specialization, param)); - body.end().end(); + body.string(castValueName(targetParameter)); } } } @@ -173,6 +189,14 @@ return prefix; } + private static CodeTree createCallTypeSystemMethod(ProcessorContext context, CodeTreeBuilder parent, NodeData node, String methodName, String value) { + CodeTreeBuilder builder = new CodeTreeBuilder(parent); + startCallTypeSystemMethod(context, builder, node, methodName); + builder.string(value); + builder.end().end(); + return builder.getRoot(); + } + private static void startCallTypeSystemMethod(ProcessorContext context, CodeTreeBuilder body, NodeData node, String methodName) { VariableElement singleton = TypeSystemCodeGenerator.findSingleton(context, node.getTypeSystem()); assert singleton != null; @@ -182,44 +206,205 @@ body.string(".").startCall(methodName); } - private static void emitGuards(ProcessorContext context, CodeTreeBuilder body, String prefix, SpecializationData specialization, boolean onSpecialization, boolean needsCast) { - TypeSystemData typeSystem = specialization.getNode().getTypeSystem(); - // Implict guards based on method signature - String andOperator = prefix; - if (needsCast) { - for (NodeFieldData field : specialization.getNode().getFields()) { - ActualParameter param = specialization.findParameter(field.getName()); - TypeData type = param.getActualTypeData(typeSystem); - if (type == null || type.isGeneric()) { - continue; - } + private CodeTree createGuardAndCast(CodeTreeBuilder parent, String conditionPrefix, SpecializationData valueSpecialization, SpecializationData guardedSpecialization, boolean onSpecialization, + CodeTree guardedStatements, CodeTree elseStatements) { + + CodeTreeBuilder builder = new CodeTreeBuilder(parent); + CodeTree implicitGuards = createImplicitGuards(parent, conditionPrefix, valueSpecialization, guardedSpecialization); + CodeTree explicitGuards = createExplicitGuards(parent, implicitGuards == null ? conditionPrefix : null, valueSpecialization, guardedSpecialization, onSpecialization); + + int ifCount = 0; - body.string(andOperator); - startCallTypeSystemMethod(context, body, specialization.getNode(), TypeSystemCodeGenerator.isTypeMethodName(type)); - body.string(valueName(specialization, param)); - body.end().end(); // call - andOperator = " && "; - } + if (implicitGuards != null) { + builder.startIf(); + builder.tree(implicitGuards); + builder.end(); + builder.startBlock(); + ifCount++; + } + + if (explicitGuards != null || !onSpecialization) { + builder.tree(createCasts(parent, valueSpecialization, guardedSpecialization)); + } + + if (explicitGuards != null) { + builder.startIf(); + builder.tree(explicitGuards); + builder.end(); + builder.startBlock(); + ifCount++; } - if (specialization.getGuards().length > 0) { - // Explicitly specified guards - for (SpecializationGuardData guard : specialization.getGuards()) { - if ((guard.isOnSpecialization() && onSpecialization) || (guard.isOnExecution() && !onSpecialization)) { - body.string(andOperator); + if (implicitGuards == null && explicitGuards == null && conditionPrefix != null && !conditionPrefix.isEmpty()) { + builder.startIf().string(conditionPrefix).end().startBlock(); + ifCount++; + } + + builder.tree(guardedStatements); + + builder.end(ifCount); + if (ifCount > 0 && elseStatements != null) { + builder.startElseBlock(); + builder.tree(elseStatements); + builder.end(); + } - startCallOperationMethod(body, guard.getGuardDeclaration()); + return builder.getRoot(); + } - if (needsCast) { - addValueParameterNamesWithCasts(context, body, specialization); - } else { - addValueParameterNames(body, specialization, null, false); - } - body.end().end(); // call + private static CodeTree createExplicitGuards(CodeTreeBuilder parent, String conditionPrefix, SpecializationData valueSpecialization, SpecializationData guardedSpecialization, + boolean onSpecialization) { + CodeTreeBuilder builder = new CodeTreeBuilder(parent); + String andOperator = conditionPrefix != null ? conditionPrefix + " && " : ""; + if (guardedSpecialization.getGuards().length > 0) { + // Explicitly specified guards + for (SpecializationGuardData guard : guardedSpecialization.getGuards()) { + if ((guard.isOnSpecialization() && onSpecialization) || (guard.isOnExecution() && !onSpecialization)) { + builder.string(andOperator); + + startCallOperationMethod(builder, guard.getGuardDeclaration()); + addValueParameterNamesWithCasts(builder, valueSpecialization, guardedSpecialization); + + builder.end().end(); // call andOperator = " && "; } } } + + return builder.isEmpty() ? null : builder.getRoot(); + } + + private CodeTree createCasts(CodeTreeBuilder parent, SpecializationData valueSpecialization, SpecializationData guardedSpecialization) { + NodeData node = guardedSpecialization.getNode(); + + CodeTreeBuilder builder = new CodeTreeBuilder(parent); + // Implict guards based on method signature + for (NodeFieldData field : node.getFields()) { + ActualParameter guardedParam = guardedSpecialization.findParameter(field.getName()); + ActualParameter valueParam = valueSpecialization.findParameter(field.getName()); + + CodeTree cast = createCast(parent, field, valueParam, guardedParam); + if (cast == null) { + continue; + } + builder.tree(cast); + } + + return builder.getRoot(); + } + + private CodeTree createImplicitGuards(CodeTreeBuilder parent, String conditionPrefix, SpecializationData valueSpecialization, SpecializationData guardedSpecialization) { + NodeData node = guardedSpecialization.getNode(); + + CodeTreeBuilder builder = new CodeTreeBuilder(parent); + // Implict guards based on method signature + String andOperator = conditionPrefix != null ? conditionPrefix + " && " : ""; + for (NodeFieldData field : node.getFields()) { + ActualParameter guardedParam = guardedSpecialization.findParameter(field.getName()); + ActualParameter valueParam = valueSpecialization.findParameter(field.getName()); + + CodeTree implicitGuard = createImplicitGuard(builder, field, valueParam, guardedParam); + if (implicitGuard == null) { + continue; + } + + builder.string(andOperator); + builder.tree(implicitGuard); + andOperator = " && "; + } + + return builder.isEmpty() ? null : builder.getRoot(); + } + + private CodeTree createImplicitGuard(CodeTreeBuilder parent, NodeFieldData field, ActualParameter source, ActualParameter target) { + NodeData node = field.getNodeData(); + CodeTreeBuilder builder = new CodeTreeBuilder(parent); + + TypeData targetType = target.getActualTypeData(node.getTypeSystem()); + TypeData sourceType = source.getActualTypeData(node.getTypeSystem()); + + if (targetType.equalsType(sourceType) || targetType.isGeneric()) { + return null; + } + + builder.startGroup(); + + if (field.isShortCircuit()) { + ActualParameter shortCircuit = target.getPreviousParameter(); + assert shortCircuit != null; + builder.string("("); + builder.string("!").string(valueName(shortCircuit)); + builder.string(" || "); + } + + startCallTypeSystemMethod(getContext(), builder, node, TypeSystemCodeGenerator.isTypeMethodName(target.getActualTypeData(node.getTypeSystem()))); + builder.string(valueName(field)); + builder.end().end(); // call + + if (field.isShortCircuit()) { + builder.string(")"); + } + + builder.end(); // group + + return builder.getRoot(); + } + + private CodeTree createCast(CodeTreeBuilder parent, NodeFieldData field, ActualParameter source, ActualParameter target) { + NodeData node = field.getNodeData(); + TypeSystemData typeSystem = node.getTypeSystem(); + + TypeData sourceType = source.getActualTypeData(typeSystem); + TypeData targetType = target.getActualTypeData(typeSystem); + + if (targetType.equalsType(sourceType) || targetType.isGeneric()) { + return null; + } + + CodeTree condition = null; + if (field.isShortCircuit()) { + ActualParameter shortCircuit = target.getPreviousParameter(); + assert shortCircuit != null; + condition = CodeTreeBuilder.singleString(valueName(shortCircuit)); + } + + CodeTree value = createCallTypeSystemMethod(context, parent, node, TypeSystemCodeGenerator.asTypeMethodName(targetType), valueName(target)); + + return createLazyAssignment(parent, castValueName(field), target.getActualType(), condition, value); + } + + /** + *
+     * variant1 $condition != null
+     * 
+     * $type $name = defaultValue($type);
+     * if ($condition) {
+     *     $name = $value;
+     * }
+     * 
+     * variant2 $condition != null
+     * $type $name = $value;
+     * 
+ * + * . + */ + private static CodeTree createLazyAssignment(CodeTreeBuilder parent, String name, TypeMirror type, CodeTree condition, CodeTree value) { + CodeTreeBuilder builder = new CodeTreeBuilder(parent); + if (condition == null) { + builder.declaration(type, name, value); + } else { + builder.declaration(type, name, new CodeTreeBuilder(parent).defaultValue(type).getRoot()); + + builder.startIf().tree(condition).end(); + builder.startBlock(); + builder.startStatement(); + builder.string(name); + builder.string(" = "); + builder.tree(value); + builder.end(); // statement + builder.end(); // block + } + return builder.getRoot(); } @Override @@ -436,17 +621,12 @@ SpecializationData specialization = node.getSpecializations()[i]; body.startStatement().string("allowed = allowed || (minimumState == ").string(nodeClassName(specialization)).string(".class)").end(); - if (specialization.isGeneric()) { - body.startIf().string("allowed").end().startBlock(); - } else { - body.startIf().string("allowed"); - emitGuards(getContext(), body, " && ", specialization, true, true); - body.end().startBlock(); - } - body.startReturn().startNew(nodeClassName(specialization)); - body.string(THIS_NODE_LOCAL_VAR_NAME); - body.end().end(); - body.end(); // block + CodeTreeBuilder guarded = new CodeTreeBuilder(body); + guarded.startReturn().startNew(nodeClassName(specialization)); + guarded.string(THIS_NODE_LOCAL_VAR_NAME); + guarded.end().end(); + + body.tree(createGuardAndCast(body, "allowed", node.getGenericSpecialization(), specialization, true, guarded.getRoot(), null)); } body.startThrow().startNew(getContext().getType(IllegalArgumentException.class)).end().end(); @@ -490,24 +670,23 @@ } private void emitGeneratedGenericSpecialization(CodeTreeBuilder builder, SpecializationData current, SpecializationData next) { + CodeTreeBuilder invokeMethodBuilder = new CodeTreeBuilder(builder); + emitInvokeDoMethod(invokeMethodBuilder, current, 0); + CodeTree invokeMethod = invokeMethodBuilder.getRoot(); + if (next != null) { - builder.startIf(); - emitGuards(context, builder, "", current, false, true); - builder.end().startBlock(); + invokeMethod = createGuardAndCast(builder, null, current.getNode().getGenericSpecialization(), current, false, invokeMethod, null); } - emitInvokeDoMethod(builder, current, 0); + builder.tree(invokeMethod); if (next != null) { builder.end(); - builder.startElseBlock(); builder.startReturn().startCall(generatedGenericMethodName(next)); builder.string(THIS_NODE_LOCAL_VAR_NAME); addValueParameterNames(builder, next, null, true); builder.end().end(); - - builder.end(); } } @@ -518,7 +697,7 @@ builder.startReturn(); startCallOperationMethod(builder, specialization); - addValueParameterNamesWithCasts(context, builder, specialization); + addValueParameterNamesWithCasts(builder, specialization.getNode().getGenericSpecialization(), specialization); builder.end().end(); // start call operation builder.end(); // return @@ -625,14 +804,14 @@ builder.string("// ignore").newLine(); } else { builder.startReturn(); - builder.tree(castPrimaryExecute(node, castedType, CodeTreeBuilder.singleString("ex.getResult()"))); + builder.tree(createExpectType(node, castedType, CodeTreeBuilder.singleString("ex.getResult()"))); builder.end(); } builder.end(); if (!returnVoid) { builder.startReturn(); - builder.tree(castPrimaryExecute(node, castedType, CodeTreeBuilder.singleString("value"))); + builder.tree(createExpectType(node, castedType, CodeTreeBuilder.singleString("value"))); builder.end(); } } else { @@ -640,81 +819,92 @@ builder.statement(primaryExecuteCall); } else { builder.startReturn(); - builder.tree(castPrimaryExecute(node, castedType, primaryExecuteCall)); + builder.tree(createExpectType(node, castedType, primaryExecuteCall)); builder.end(); } } } - private CodeTree castPrimaryExecute(NodeData node, ExecutableTypeData castedType, CodeTree value) { - if (castedType.getType().isVoid()) { + private CodeTree createExpectType(NodeData node, ExecutableTypeData castedType, CodeTree value) { + if (castedType == null) { return value; - } - if (castedType.getType().isGeneric()) { + } else if (castedType.getType().isVoid()) { + return value; + } else if (castedType.getType().isGeneric()) { return value; } CodeTreeBuilder builder = CodeTreeBuilder.createBuilder(); + String targetMethodName; if (castedType.hasUnexpectedValue(getContext())) { - startCallTypeSystemMethod(getContext(), builder, node, TypeSystemCodeGenerator.expectTypeMethodName(castedType.getType())); + targetMethodName = TypeSystemCodeGenerator.expectTypeMethodName(castedType.getType()); } else { - startCallTypeSystemMethod(getContext(), builder, node, TypeSystemCodeGenerator.asTypeMethodName(castedType.getType())); + targetMethodName = TypeSystemCodeGenerator.asTypeMethodName(castedType.getType()); } + startCallTypeSystemMethod(getContext(), builder, node, targetMethodName); + builder.tree(value); builder.end().end(); return builder.getRoot(); } private void buildFunctionalExecuteMethod(CodeTreeBuilder builder, SpecializationData specialization) { - NodeData node = specialization.getNode(); - TypeSystemData typeSystem = node.getTypeSystem(); - - for (NodeFieldData field : node.getFields()) { - if (field.getExecutionKind() == ExecutionKind.IGNORE) { - continue; - } + if (specialization.isUninitialized()) { + builder.tree(createDeoptimize(builder)); + } - ActualParameter parameterType = specialization.findParameter(field.getName()); + builder.tree(createExecuteChildren(builder, specialization)); - if (parameterType.getActualTypeData(typeSystem).isGeneric()) { - buildGenericValueExecute(builder, specialization, field, null); - } else { - buildSpecializedValueExecute(builder, specialization, field); - } + if (specialization.isUninitialized()) { + builder.tree(createSpecializeCall(builder, specialization)); } - if (specialization.hasDynamicGuards()) { - builder.startIf(); - emitGuards(getContext(), builder, "", specialization, false, false); - builder.end().startBlock(); + CodeTree executeNode = createExecute(builder, specialization); + + SpecializationData next = specialization.findNextSpecialization(); + CodeTree returnSpecialized = null; + if (next != null) { + returnSpecialized = createReturnSpecializeAndExecute(builder, next, null); } + builder.tree(createGuardAndCast(builder, null, specialization, specialization, false, executeNode, returnSpecialized)); + } + + private CodeTree createDeoptimize(CodeTreeBuilder parent) { + CodeTreeBuilder builder = new CodeTreeBuilder(parent); + builder.startStatement(); + builder.startStaticCall(getContext().getTruffleTypes().getTruffleIntrinsics(), "deoptimize").end(); + builder.end(); + return builder.getRoot(); + } + + private CodeTree createSpecializeCall(CodeTreeBuilder parent, SpecializationData specialization) { + NodeData node = specialization.getNode(); + + CodeTreeBuilder builder = new CodeTreeBuilder(parent); + emitSpecializationListeners(builder, node); + + builder.startStatement(); + builder.startCall("replace"); + if (node.needsRewrites(getContext())) { + builder.startCall(factoryClassName(node), "specialize"); + builder.string("this"); + builder.typeLiteral(builder.findMethod().getEnclosingElement().asType()); + addValueParameterNames(builder, specialization, null, false); + builder.end(); // call replace, call specialize + } else { + builder.startCall(factoryClassName(node), "createSpecialized").string("this").string("null").end(); + } + builder.end().end(); + return builder.getRoot(); + } + + private CodeTree createExecute(CodeTreeBuilder parent, SpecializationData specialization) { + NodeData node = specialization.getNode(); + CodeTreeBuilder builder = new CodeTreeBuilder(parent); if (specialization.getExceptions().length > 0) { builder.startTryBlock(); } - if (specialization.isUninitialized()) { - for (TemplateMethod listener : node.getSpecializationListeners()) { - builder.startStatement(); - startCallOperationMethod(builder, listener); - addValueParameterNames(builder, listener, null, false); - builder.end().end(); - builder.end(); // statement - } - - builder.startStatement(); - builder.startCall("replace"); - if (node.needsRewrites(getContext())) { - builder.startCall(factoryClassName(node), "specialize"); - builder.string("this"); - builder.typeLiteral(builder.getRoot().getEnclosingClass().asType()); - addValueParameterNames(builder, specialization, null, false); - builder.end(); // call replace, call specialize - } else { - builder.startCall(factoryClassName(node), "createSpecialized").string("this").string("null").end(); - } - builder.end().end(); - } - if ((specialization.isUninitialized() || specialization.isGeneric()) && node.needsRewrites(getContext())) { builder.startReturn().startCall(factoryClassName(node), generatedGenericMethodName(null)); builder.string("this"); @@ -736,14 +926,38 @@ if (specialization.getExceptions().length > 0) { for (SpecializationThrowsData exception : specialization.getExceptions()) { builder.end().startCatchBlock(exception.getJavaClass(), "ex"); - buildThrowSpecialize(builder, specialization, exception.getTransitionTo(), null); + builder.tree(createReturnSpecializeAndExecute(parent, exception.getTransitionTo(), null)); } builder.end(); } - if (specialization.hasDynamicGuards()) { - builder.end().startElseBlock(); - buildThrowSpecialize(builder, specialization, specialization.findNextSpecialization(), null); - builder.end(); + return builder.getRoot(); + } + + private CodeTree createExecuteChildren(CodeTreeBuilder parent, SpecializationData specialization) { + CodeTreeBuilder builder = new CodeTreeBuilder(parent); + for (NodeFieldData field : specialization.getNode().getFields()) { + if (field.getExecutionKind() == ExecutionKind.IGNORE) { + continue; + } + + ActualParameter parameterType = specialization.findParameter(field.getName()); + + if (parameterType.getActualTypeData(specialization.getNode().getTypeSystem()).isGeneric()) { + buildGenericValueExecute(builder, specialization, field, null); + } else { + buildSpecializedValueExecute(builder, specialization, field); + } + } + return builder.getRoot(); + } + + private void emitSpecializationListeners(CodeTreeBuilder builder, NodeData node) { + for (TemplateMethod listener : node.getSpecializationListeners()) { + builder.startStatement(); + startCallOperationMethod(builder, listener); + addValueParameterNames(builder, listener, null, false); + builder.end().end(); + builder.end(); // statement } } @@ -758,7 +972,7 @@ builder.string(" "); } - builder.string(valueName(specialization, specParameter)); + builder.string(valueName(specParameter)); builder.string(" = "); ExecutableTypeData genericExecutableType = field.getNodeData().findGenericExecutableType(getContext(), specParameter.getActualTypeData(node.getTypeSystem())); if (genericExecutableType == null) { @@ -794,7 +1008,7 @@ boolean shortCircuit = startShortCircuit(builder, specialization, field, null); if (!shortCircuit) { - builder.startStatement().type(param.getActualType()).string(" ").string(valueName(specialization, param)).end(); + builder.startStatement().type(param.getActualType()).string(" ").string(valueName(param)).end(); } ExecutableTypeData execType = field.getNodeData().findExecutableType(param.getActualTypeData(field.getNodeData().getTypeSystem())); @@ -820,7 +1034,7 @@ execute = true; } } - buildThrowSpecialize(builder, specialization, specialization.findNextSpecialization(), param.getSpecification()); + builder.tree(createReturnSpecializeAndExecute(builder, specialization.findNextSpecialization(), param.getSpecification())); builder.end(); // catch block } @@ -846,7 +1060,7 @@ } } - builder.startStatement().type(shortCircuitParam.getActualType()).string(" ").string(valueName(specialization, shortCircuitParam)).string(" = "); + builder.startStatement().type(shortCircuitParam.getActualType()).string(" ").string(valueName(shortCircuitParam)).string(" = "); ShortCircuitData shortCircuitData = specialization.getShortCircuits()[shortCircuitIndex]; startCallOperationMethod(builder, shortCircuitData); @@ -855,7 +1069,7 @@ builder.end(); // statement - builder.declaration(parameter.getActualType(), valueName(specialization, parameter), CodeTreeBuilder.createBuilder().defaultValue(parameter.getActualType())); + builder.declaration(parameter.getActualType(), valueName(parameter), CodeTreeBuilder.createBuilder().defaultValue(parameter.getActualType())); builder.startIf().string(shortCircuitParam.getSpecification().getName()).end(); builder.startBlock(); @@ -868,50 +1082,38 @@ } } - private void buildThrowSpecialize(CodeTreeBuilder builder, SpecializationData currentSpecialization, SpecializationData nextSpecialization, ParameterSpec exceptionSpec) { - boolean canThrowUnexpected = Utils.canThrowType(builder.findMethod().getThrownTypes(), getContext().getTruffleTypes().getUnexpectedValueException()); - - CodeTreeBuilder specializeCall = CodeTreeBuilder.createBuilder(); - specializeCall.startCall("specialize"); + private CodeTree createReturnSpecializeAndExecute(CodeTreeBuilder parent, SpecializationData nextSpecialization, ParameterSpec exceptionSpec) { + CodeTreeBuilder specializeCall = new CodeTreeBuilder(parent); + specializeCall.startCall("specializeAndExecute"); specializeCall.string(nodeClassName(nextSpecialization) + ".class"); addValueParameterNames(specializeCall, nextSpecialization.getNode().getGenericSpecialization(), exceptionSpec != null ? exceptionSpec.getName() : null, true); specializeCall.end().end(); - TypeData expectedType = currentSpecialization.getReturnType().getActualTypeData(currentSpecialization.getNode().getTypeSystem()); - if (canThrowUnexpected) { - builder.startReturn(); - startCallTypeSystemMethod(context, builder, currentSpecialization.getNode(), TypeSystemCodeGenerator.expectTypeMethodName(expectedType)); - builder.tree(specializeCall.getRoot()); - builder.end().end(); - builder.end(); // return - } else { - builder.startReturn(); - if (!expectedType.isVoid() && !expectedType.isGeneric()) { - startCallTypeSystemMethod(context, builder, currentSpecialization.getNode(), TypeSystemCodeGenerator.asTypeMethodName(expectedType)); - builder.tree(specializeCall.getRoot()); - builder.end().end(); - } else { - builder.tree(specializeCall.getRoot()); - } - builder.end(); - } - + CodeTreeBuilder builder = new CodeTreeBuilder(parent); + builder.startReturn(); + builder.tree(specializeCall.getRoot()); + builder.end(); + return builder.getRoot(); } private void buildSpecializeStateMethod(CodeTypeElement clazz, SpecializationData specialization) { - CodeExecutableElement method = new CodeExecutableElement(modifiers(PRIVATE), specialization.getNode().getTypeSystem().getGenericType(), "specialize"); + NodeData node = specialization.getNode(); + TypeData returnType = specialization.getReturnType().getActualTypeData(node.getTypeSystem()); + ExecutableTypeData returnExecutableType = node.findExecutableType(returnType); + boolean canThrowUnexpected = returnExecutableType == null ? true : returnExecutableType.hasUnexpectedValue(getContext()); + + CodeExecutableElement method = new CodeExecutableElement(modifiers(PRIVATE), returnType.getPrimitiveType(), "specializeAndExecute"); method.addParameter(new CodeVariableElement(getContext().getType(Class.class), "minimumState")); + if (canThrowUnexpected) { + method.addThrownType(getUnexpectedValueException()); + } addValueParameters(method, specialization.getNode().getGenericSpecialization(), true); clazz.add(method); CodeTreeBuilder builder = method.createBuilder(); - for (TemplateMethod listener : specialization.getNode().getSpecializationListeners()) { - builder.startStatement(); - startCallOperationMethod(builder, listener); - addValueParameterNames(builder, listener, null, false); - builder.end().end(); // call operation - builder.end(); // statement - } + + builder.tree(createDeoptimize(builder)); + emitSpecializationListeners(builder, specialization.getNode()); builder.startStatement(); builder.startCall("replace"); @@ -922,20 +1124,24 @@ builder.end(); // statement String generatedMethodName = generatedGenericMethodName(specialization.findNextSpecialization()); - ExecutableElement generatedGeneric = clazz.getEnclosingClass().getMethod(generatedMethodName); - CodeTreeBuilder genericBuilder = CodeTreeBuilder.createBuilder(); - genericBuilder.startCall(factoryClassName(specialization.getNode()), generatedMethodName); - genericBuilder.string("this"); - addValueParameterNames(genericBuilder, specialization.getNode().getGenericSpecialization(), null, true); - genericBuilder.end(); // call generated generic + CodeTreeBuilder genericExecute = CodeTreeBuilder.createBuilder(); + genericExecute.startCall(factoryClassName(specialization.getNode()), generatedMethodName); + genericExecute.string("this"); + addValueParameterNames(genericExecute, specialization.getNode().getGenericSpecialization(), null, true); + genericExecute.end(); // call generated generic + + CodeTree genericInvocation = createExpectType(node, returnExecutableType, genericExecute.getRoot()); if (generatedGeneric != null && Utils.isVoid(generatedGeneric.getReturnType())) { - builder.declaration(generatedGeneric.getReturnType(), "genericResult", genericBuilder.getRoot()); - builder.startReturn().string("null").end(); + builder.statement(genericInvocation); + + if (!Utils.isVoid(builder.findMethod().asType())) { + builder.startReturn().defaultValue(returnType.getPrimitiveType()).end(); + } } else { - builder.startReturn().tree(genericBuilder.getRoot()).end(); + builder.startReturn().tree(genericInvocation).end(); } } diff -r 8959b331ef3e -r 268d3e74191e graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeFieldData.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeFieldData.java Tue Feb 19 16:03:11 2013 +0100 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/NodeFieldData.java Tue Feb 19 17:41:10 2013 +0100 @@ -52,6 +52,10 @@ this.executionKind = executionKind; } + public boolean isShortCircuit() { + return executionKind == ExecutionKind.SHORT_CIRCUIT; + } + public VariableElement getFieldElement() { return fieldElement; } diff -r 8959b331ef3e -r 268d3e74191e graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/SpecializationData.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/SpecializationData.java Tue Feb 19 16:03:11 2013 +0100 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/node/SpecializationData.java Tue Feb 19 17:41:10 2013 +0100 @@ -124,15 +124,4 @@ return false; } - public ActualParameter getPreviousParam(ActualParameter searchParam) { - ActualParameter prev = null; - for (ActualParameter param : getParameters()) { - if (param == searchParam) { - return prev; - } - prev = param; - } - return prev; - } - } diff -r 8959b331ef3e -r 268d3e74191e graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/ActualParameter.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/ActualParameter.java Tue Feb 19 16:03:11 2013 +0100 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/ActualParameter.java Tue Feb 19 17:41:10 2013 +0100 @@ -30,16 +30,25 @@ private final ParameterSpec specification; private final TypeMirror actualType; + private TemplateMethod method; public ActualParameter(ParameterSpec specification, TypeMirror actualType) { this.specification = specification; this.actualType = actualType; } + void setMethod(TemplateMethod method) { + this.method = method; + } + public ParameterSpec getSpecification() { return specification; } + public TemplateMethod getMethod() { + return method; + } + public TypeMirror getActualType() { return actualType; } @@ -47,4 +56,8 @@ public TypeData getActualTypeData(TypeSystemData typeSystem) { return typeSystem.findTypeData(actualType); } + + public ActualParameter getPreviousParameter() { + return method.getPreviousParam(this); + } } diff -r 8959b331ef3e -r 268d3e74191e graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/TemplateMethod.java --- a/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/TemplateMethod.java Tue Feb 19 16:03:11 2013 +0100 +++ b/graal/com.oracle.truffle.codegen.processor/src/com/oracle/truffle/codegen/processor/template/TemplateMethod.java Tue Feb 19 17:41:10 2013 +0100 @@ -40,15 +40,16 @@ this.markerAnnotation = markerAnnotation; this.returnType = returnType; this.parameters = parameters; + + if (parameters != null) { + for (ActualParameter param : parameters) { + param.setMethod(this); + } + } } public TemplateMethod(TemplateMethod method) { - this.template = method.template; - this.specification = method.specification; - this.method = method.method; - this.markerAnnotation = method.markerAnnotation; - this.returnType = method.returnType; - this.parameters = method.parameters; + this(method.template, method.specification, method.method, method.markerAnnotation, method.returnType, method.parameters); } public Template getTemplate() { @@ -101,4 +102,15 @@ public String toString() { return getClass().getSimpleName() + " [method = " + method + "]"; } + + public ActualParameter getPreviousParam(ActualParameter searchParam) { + ActualParameter prev = null; + for (ActualParameter param : getParameters()) { + if (param == searchParam) { + return prev; + } + prev = param; + } + return prev; + } } diff -r 8959b331ef3e -r 268d3e74191e graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/TernaryTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.truffle.sl.test/src/com/oracle/truffle/sl/test/TernaryTest.java Tue Feb 19 17:41:10 2013 +0100 @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2012, 2012, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.truffle.sl.test; + +import org.junit.*; + +// @formatter:off +public class TernaryTest extends AbstractTest { + + private static String[] INPUT = new String[] { +"function main { " + +" print #(1 < 2) ? 1 : 2;" + +" print #(2 < 1) ? 100000000000000 : 1; ", +" print #(1 < 2) ? 100000000000000 : 1; ", +" print #(2 < 1) ? \"wrong\" : \"true\";", +" print #(2 < 1) ? \"wrong\" : 1;", +"} ", + }; + + private static String[] OUTPUT = new String[] { + "1", + "1", + "100000000000000", + "true", + "1", + }; + + @Test + public void test() { + executeSL(INPUT, OUTPUT, true); + } +} diff -r 8959b331ef3e -r 268d3e74191e graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/NodeFactory.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/NodeFactory.java Tue Feb 19 16:03:11 2013 +0100 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/NodeFactory.java Tue Feb 19 17:41:10 2013 +0100 @@ -127,4 +127,8 @@ StatementNode write = WriteLocalNodeFactory.create(slot, value); return new ReturnNode(write); } + + public TypedNode createTernary(TypedNode condition, TypedNode thenPart, TypedNode elsePart) { + return TernaryNodeFactory.create(condition, thenPart, elsePart); + } } diff -r 8959b331ef3e -r 268d3e74191e graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/nodes/TernaryNode.java diff -r 8959b331ef3e -r 268d3e74191e graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Parser.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Parser.java Tue Feb 19 16:03:11 2013 +0100 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Parser.java Tue Feb 19 17:41:10 2013 +0100 @@ -21,10 +21,9 @@ * questions. */ -// The content of this file is automatically generated. DO NOT EDIT. + // The content of this file is automatically generated. DO NOT EDIT. package com.oracle.truffle.sl.parser; - import java.util.*; import com.oracle.truffle.sl.*; @@ -33,11 +32,11 @@ // Checkstyle: stop // @formatter:off public class Parser { - public static final int _EOF = 0; - public static final int _identifier = 1; - public static final int _stringLiteral = 2; - public static final int _numericLiteral = 3; - public static final int maxT = 25; + public static final int _EOF = 0; + public static final int _identifier = 1; + public static final int _stringLiteral = 2; + public static final int _numericLiteral = 3; + public static final int maxT = 28; static final boolean T = true; static final boolean x = false; @@ -50,7 +49,7 @@ public final Scanner scanner; public final Errors errors; private final NodeFactory factory; - + public Parser(Scanner scanner, NodeFactory factory) { this.scanner = scanner; this.factory = factory; @@ -121,226 +120,255 @@ } } - void SimpleLanguage() { - Function(); - while (la.kind == 4) { - Function(); - } - } - - void Function() { - Expect(4); - factory.startFunction(); - Expect(1); - String name = t.val; - StatementNode body = Block(); - factory.createFunction(body, name); - } - - StatementNode Block() { - StatementNode result; - List statements = new ArrayList<>(); - Expect(5); - while (StartOf(1)) { - StatementNode statement = Statement(); - statements.add(statement); - } - Expect(6); - result = factory.createBlock(statements); - return result; - } - - StatementNode Statement() { - StatementNode result; - result = null; - if (la.kind == 7) { - result = WhileStatement(); - } else if (la.kind == 1) { - result = AssignmentStatement(); - } else if (la.kind == 12) { - result = OutputStatement(); - } else if (la.kind == 13) { - result = ReturnStatement(); - } else SynErr(26); - return result; - } - - StatementNode WhileStatement() { - StatementNode result; - Expect(7); - Expect(8); - ConditionNode condition = Expression(); - Expect(9); - StatementNode body = Block(); - result = factory.createWhile(condition, body); - return result; - } - - StatementNode AssignmentStatement() { - StatementNode result; - Expect(1); - String name = t.val; - Expect(10); - TypedNode rvalue = Expression(); - Expect(11); - result = factory.createAssignment(name, rvalue); - return result; - } - - StatementNode OutputStatement() { - StatementNode result; - List expressions = new ArrayList<>(); - Expect(12); - while (StartOf(2)) { - TypedNode value = Expression(); - expressions.add(value); - } - Expect(11); - result = factory.createPrint(expressions); - return result; - } - - StatementNode ReturnStatement() { - StatementNode result; - Expect(13); - TypedNode value = Expression(); - Expect(11); - result = factory.createReturn(value); - return result; - } - - TypedNode Expression() { - TypedNode result; - result = ValueExpression(); - if (StartOf(3)) { - switch (la.kind) { - case 14: { - Get(); - break; - } - case 15: { - Get(); - break; - } - case 16: { - Get(); - break; - } - case 17: { - Get(); - break; - } - case 18: { - Get(); - break; - } - case 19: { - Get(); - break; - } - } - String op = t.val; - TypedNode right = ValueExpression(); - result = factory.createBinary(op, result, right); - } - return result; - } - - TypedNode ValueExpression() { - TypedNode result; - result = Term(); - while (la.kind == 20 || la.kind == 21) { - if (la.kind == 20) { - Get(); - } else { - Get(); - } - String op = t.val; - TypedNode right = Term(); - result = factory.createBinary(op, result, right); - } - return result; - } - - TypedNode Term() { - TypedNode result; - result = Factor(); - while (la.kind == 22 || la.kind == 23) { - if (la.kind == 22) { - Get(); - } else { - Get(); - } - String op = t.val; - TypedNode right = Factor(); - result = factory.createBinary(op, result, right); - } - return result; - } - - TypedNode Factor() { - TypedNode result; - result = null; - if (la.kind == 24) { - result = TimeRef(); - } else if (la.kind == 1) { - result = VariableRef(); - } else if (la.kind == 2) { - result = StringLiteral(); - } else if (la.kind == 3) { - result = NumericLiteral(); - } else if (la.kind == 8) { - Get(); - result = Expression(); - Expect(9); - } else SynErr(27); - return result; - } - - TypedNode TimeRef() { - TypedNode result; - Expect(24); - result = factory.createTime(); - return result; - } - - TypedNode VariableRef() { - TypedNode result; - Expect(1); - result = factory.createLocal(t.val); - return result; - } - - TypedNode StringLiteral() { - TypedNode result; - Expect(2); - result = factory.createStringLiteral(t.val.substring(1, t.val.length() - 1)); - return result; - } - - TypedNode NumericLiteral() { - TypedNode result; - Expect(3); - result = factory.createNumericLiteral(t.val); - return result; - } - + void SimpleLanguage() { + Function(); + while (la.kind == 4) { + Function(); + } + } + + void Function() { + Expect(4); + factory.startFunction(); + Expect(1); + String name = t.val; + StatementNode body = Block(); + factory.createFunction(body, name); + } + + StatementNode Block() { + StatementNode result; + List statements = new ArrayList<>(); + Expect(5); + while (StartOf(1)) { + StatementNode statement = Statement(); + statements.add(statement); + } + Expect(6); + result = factory.createBlock(statements); + return result; + } + + StatementNode Statement() { + StatementNode result; + result = null; + if (la.kind == 7) { + result = WhileStatement(); + } else if (la.kind == 1) { + result = AssignmentStatement(); + } else if (la.kind == 12) { + result = OutputStatement(); + } else if (la.kind == 13) { + result = ReturnStatement(); + } else SynErr(29); + return result; + } + + StatementNode WhileStatement() { + StatementNode result; + Expect(7); + Expect(8); + ConditionNode condition = Expression(); + Expect(9); + StatementNode body = Block(); + result = factory.createWhile(condition, body); + return result; + } + + StatementNode AssignmentStatement() { + StatementNode result; + Expect(1); + String name = t.val; + Expect(10); + TypedNode rvalue = Expression(); + Expect(11); + result = factory.createAssignment(name, rvalue); + return result; + } + + StatementNode OutputStatement() { + StatementNode result; + List expressions = new ArrayList<>(); + Expect(12); + while (StartOf(2)) { + TypedNode value = Expression(); + expressions.add(value); + } + Expect(11); + result = factory.createPrint(expressions); + return result; + } + + StatementNode ReturnStatement() { + StatementNode result; + Expect(13); + TypedNode value = Expression(); + Expect(11); + result = factory.createReturn(value); + return result; + } + + TypedNode Expression() { + TypedNode result; + result = ValueExpression(); + if (StartOf(3)) { + switch (la.kind) { + case 14: { + Get(); + break; + } + case 15: { + Get(); + break; + } + case 16: { + Get(); + break; + } + case 17: { + Get(); + break; + } + case 18: { + Get(); + break; + } + case 19: { + Get(); + break; + } + } + String op = t.val; + TypedNode right = ValueExpression(); + result = factory.createBinary(op, result, right); + } + return result; + } + + TypedNode ValueExpression() { + TypedNode result; + result = Term(); + while (la.kind == 20 || la.kind == 21) { + if (la.kind == 20) { + Get(); + } else { + Get(); + } + String op = t.val; + TypedNode right = Term(); + result = factory.createBinary(op, result, right); + } + return result; + } + + TypedNode Term() { + TypedNode result; + result = Factor(); + while (la.kind == 22 || la.kind == 23) { + if (la.kind == 22) { + Get(); + } else { + Get(); + } + String op = t.val; + TypedNode right = Factor(); + result = factory.createBinary(op, result, right); + } + return result; + } + + TypedNode Factor() { + TypedNode result; + result = null; + switch (la.kind) { + case 27: { + result = TimeRef(); + break; + } + case 1: { + result = VariableRef(); + break; + } + case 2: { + result = StringLiteral(); + break; + } + case 3: { + result = NumericLiteral(); + break; + } + case 24: { + result = Ternary(); + break; + } + case 8: { + Get(); + result = Expression(); + Expect(9); + break; + } + default: SynErr(30); break; + } + return result; + } + + TypedNode TimeRef() { + TypedNode result; + Expect(27); + result = factory.createTime(); + return result; + } + + TypedNode VariableRef() { + TypedNode result; + Expect(1); + result = factory.createLocal(t.val); + return result; + } + + TypedNode StringLiteral() { + TypedNode result; + Expect(2); + result = factory.createStringLiteral(t.val.substring(1, t.val.length() - 1)); + return result; + } + + TypedNode NumericLiteral() { + TypedNode result; + Expect(3); + result = factory.createNumericLiteral(t.val); + return result; + } + + TypedNode Ternary() { + TypedNode result; + TypedNode condition, thenPart, elsePart; + Expect(24); + condition = Expression(); + Expect(25); + thenPart = Expression(); + Expect(26); + elsePart = Expression(); + result = factory.createTernary(condition, thenPart, elsePart); + return result; + } + public void Parse() { la = new Token(); la.val = ""; Get(); - SimpleLanguage(); - Expect(0); + SimpleLanguage(); + Expect(0); } private static final boolean[][] set = { - {T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x}, - {x,T,x,x, x,x,x,T, x,x,x,x, T,T,x,x, x,x,x,x, x,x,x,x, x,x,x}, - {x,T,T,T, x,x,x,x, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, T,x,x}, - {x,x,x,x, x,x,x,x, x,x,x,x, x,x,T,T, T,T,T,T, x,x,x,x, x,x,x} + {T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x}, + {x,T,x,x, x,x,x,T, x,x,x,x, T,T,x,x, x,x,x,x, x,x,x,x, x,x,x,x, x,x}, + {x,T,T,T, x,x,x,x, T,x,x,x, x,x,x,x, x,x,x,x, x,x,x,x, T,x,x,T, x,x}, + {x,x,x,x, x,x,x,x, x,x,x,x, x,x,T,T, T,T,T,T, x,x,x,x, x,x,x,x, x,x} }; @@ -388,35 +416,38 @@ public void SynErr(int line, int col, int n) { String s; - switch (n) { - case 0: s = "EOF expected"; break; - case 1: s = "identifier expected"; break; - case 2: s = "stringLiteral expected"; break; - case 3: s = "numericLiteral expected"; break; - case 4: s = "\"function\" expected"; break; - case 5: s = "\"{\" expected"; break; - case 6: s = "\"}\" expected"; break; - case 7: s = "\"while\" expected"; break; - case 8: s = "\"(\" expected"; break; - case 9: s = "\")\" expected"; break; - case 10: s = "\"=\" expected"; break; - case 11: s = "\";\" expected"; break; - case 12: s = "\"print\" expected"; break; - case 13: s = "\"return\" expected"; break; - case 14: s = "\"<\" expected"; break; - case 15: s = "\">\" expected"; break; - case 16: s = "\"<=\" expected"; break; - case 17: s = "\">=\" expected"; break; - case 18: s = "\"==\" expected"; break; - case 19: s = "\"!=\" expected"; break; - case 20: s = "\"+\" expected"; break; - case 21: s = "\"-\" expected"; break; - case 22: s = "\"*\" expected"; break; - case 23: s = "\"/\" expected"; break; - case 24: s = "\"time\" expected"; break; - case 25: s = "??? expected"; break; - case 26: s = "invalid Statement"; break; - case 27: s = "invalid Factor"; break; + switch (n) { + case 0: s = "EOF expected"; break; + case 1: s = "identifier expected"; break; + case 2: s = "stringLiteral expected"; break; + case 3: s = "numericLiteral expected"; break; + case 4: s = "\"function\" expected"; break; + case 5: s = "\"{\" expected"; break; + case 6: s = "\"}\" expected"; break; + case 7: s = "\"while\" expected"; break; + case 8: s = "\"(\" expected"; break; + case 9: s = "\")\" expected"; break; + case 10: s = "\"=\" expected"; break; + case 11: s = "\";\" expected"; break; + case 12: s = "\"print\" expected"; break; + case 13: s = "\"return\" expected"; break; + case 14: s = "\"<\" expected"; break; + case 15: s = "\">\" expected"; break; + case 16: s = "\"<=\" expected"; break; + case 17: s = "\">=\" expected"; break; + case 18: s = "\"==\" expected"; break; + case 19: s = "\"!=\" expected"; break; + case 20: s = "\"+\" expected"; break; + case 21: s = "\"-\" expected"; break; + case 22: s = "\"*\" expected"; break; + case 23: s = "\"/\" expected"; break; + case 24: s = "\"#\" expected"; break; + case 25: s = "\"?\" expected"; break; + case 26: s = "\":\" expected"; break; + case 27: s = "\"time\" expected"; break; + case 28: s = "??? expected"; break; + case 29: s = "invalid Statement"; break; + case 30: s = "invalid Factor"; break; default: s = "error " + n; break; diff -r 8959b331ef3e -r 268d3e74191e graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Scanner.java --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Scanner.java Tue Feb 19 16:03:11 2013 +0100 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/Scanner.java Tue Feb 19 17:41:10 2013 +0100 @@ -311,8 +311,8 @@ static final char EOL = '\n'; static final int eofSym = 0; - static final int maxT = 25; - static final int noSym = 25; + static final int maxT = 28; + static final int noSym = 28; public Buffer buffer; // scanner buffer @@ -339,27 +339,30 @@ for (int i = 65; i <= 90; ++i) start.set(i, 1); for (int i = 97; i <= 122; ++i) start.set(i, 1); for (int i = 49; i <= 57; ++i) start.set(i, 4); - start.set(34, 2); - start.set(48, 5); - start.set(123, 6); - start.set(125, 7); - start.set(40, 8); - start.set(41, 9); - start.set(61, 20); - start.set(59, 10); - start.set(60, 21); - start.set(62, 22); - start.set(33, 14); - start.set(43, 16); - start.set(45, 17); - start.set(42, 18); - start.set(47, 19); + start.set(34, 2); + start.set(48, 5); + start.set(123, 6); + start.set(125, 7); + start.set(40, 8); + start.set(41, 9); + start.set(61, 23); + start.set(59, 10); + start.set(60, 24); + start.set(62, 25); + start.set(33, 14); + start.set(43, 16); + start.set(45, 17); + start.set(42, 18); + start.set(47, 19); + start.set(35, 20); + start.set(63, 21); + start.set(58, 22); start.set(Buffer.EOF, -1); literals.put("function", new Integer(4)); literals.put("while", new Integer(7)); literals.put("print", new Integer(12)); literals.put("return", new Integer(13)); - literals.put("time", new Integer(24)); + literals.put("time", new Integer(27)); } @@ -425,7 +428,7 @@ tval = newBuf; } if (ch != Buffer.EOF) { - tval[tlen++] = (char)ch; + tval[tlen++] = (char)ch; NextCh(); } @@ -484,9 +487,9 @@ } Token NextToken() { - while (ch == ' ' || + while (ch == ' ' || ch >= 9 && ch <= 10 || ch == 13 - ) NextCh(); + ) NextCh(); if (ch == '/' && Comment0() ||ch == '/' && Comment1()) return NextToken(); int recKind = noSym; int recEnd = pos; @@ -515,60 +518,66 @@ } // NextCh already done case 1: recEnd = pos; recKind = 1; - if (ch >= '0' && ch <= '9' || ch >= 'A' && ch <= 'Z' || ch >= 'a' && ch <= 'z') {AddCh(); state = 1; break;} + if (ch >= '0' && ch <= '9' || ch >= 'A' && ch <= 'Z' || ch >= 'a' && ch <= 'z') {AddCh(); state = 1; break;} else {t.kind = 1; t.val = new String(tval, 0, tlen); CheckLiteral(); return t;} case 2: - if (ch <= 9 || ch >= 11 && ch <= 12 || ch >= 14 && ch <= '!' || ch >= '#' && ch <= '[' || ch >= ']' && ch <= 65535) {AddCh(); state = 2; break;} - else if (ch == '"') {AddCh(); state = 3; break;} + if (ch <= 9 || ch >= 11 && ch <= 12 || ch >= 14 && ch <= '!' || ch >= '#' && ch <= '[' || ch >= ']' && ch <= 65535) {AddCh(); state = 2; break;} + else if (ch == '"') {AddCh(); state = 3; break;} else {state = 0; break;} - case 3: + case 3: {t.kind = 2; break loop;} case 4: recEnd = pos; recKind = 3; - if (ch >= '0' && ch <= '9') {AddCh(); state = 4; break;} + if (ch >= '0' && ch <= '9') {AddCh(); state = 4; break;} else {t.kind = 3; break loop;} - case 5: + case 5: {t.kind = 3; break loop;} - case 6: + case 6: {t.kind = 5; break loop;} - case 7: + case 7: {t.kind = 6; break loop;} - case 8: + case 8: {t.kind = 8; break loop;} - case 9: + case 9: {t.kind = 9; break loop;} - case 10: + case 10: {t.kind = 11; break loop;} - case 11: + case 11: {t.kind = 16; break loop;} - case 12: + case 12: {t.kind = 17; break loop;} - case 13: + case 13: {t.kind = 18; break loop;} case 14: - if (ch == '=') {AddCh(); state = 15; break;} + if (ch == '=') {AddCh(); state = 15; break;} else {state = 0; break;} - case 15: + case 15: {t.kind = 19; break loop;} - case 16: + case 16: {t.kind = 20; break loop;} - case 17: + case 17: {t.kind = 21; break loop;} - case 18: + case 18: {t.kind = 22; break loop;} - case 19: + case 19: {t.kind = 23; break loop;} - case 20: + case 20: + {t.kind = 24; break loop;} + case 21: + {t.kind = 25; break loop;} + case 22: + {t.kind = 26; break loop;} + case 23: recEnd = pos; recKind = 10; - if (ch == '=') {AddCh(); state = 13; break;} + if (ch == '=') {AddCh(); state = 13; break;} else {t.kind = 10; break loop;} - case 21: + case 24: recEnd = pos; recKind = 14; - if (ch == '=') {AddCh(); state = 11; break;} + if (ch == '=') {AddCh(); state = 11; break;} else {t.kind = 14; break loop;} - case 22: + case 25: recEnd = pos; recKind = 15; - if (ch == '=') {AddCh(); state = 12; break;} + if (ch == '=') {AddCh(); state = 12; break;} else {t.kind = 15; break loop;} } diff -r 8959b331ef3e -r 268d3e74191e graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/SimpleLanguage.atg --- a/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/SimpleLanguage.atg Tue Feb 19 16:03:11 2013 +0100 +++ b/graal/com.oracle.truffle.sl/src/com/oracle/truffle/sl/parser/SimpleLanguage.atg Tue Feb 19 17:41:10 2013 +0100 @@ -131,11 +131,19 @@ | NumericLiteral | + Ternary +| "(" Expression ")" -) +) . -TimeRef +Ternary (. TypedNode condition, thenPart, elsePart; .) += +"#" Expression "?" Expression ":" Expression + (. result = factory.createTernary(condition, thenPart, elsePart); .) +. + +TimeRef = "time" (. result = factory.createTime(); .) .