├── .gitignore ├── .travis.yml ├── LICENSE ├── README.md ├── bytecode-generation ├── pom.xml └── src │ ├── main │ └── java │ │ └── me │ │ └── tomassetti │ │ ├── bytecode_generation │ │ ├── ArrayAccessBS.java │ │ ├── ArrayLengthBS.java │ │ ├── BytecodeSequence.java │ │ ├── ComposedBytecodeSequence.java │ │ ├── IfBS.java │ │ ├── IntToLongBS.java │ │ ├── LocalVarAssignmentBS.java │ │ ├── MathOperationBS.java │ │ ├── MethodInvocationBS.java │ │ ├── NewInvocationBS.java │ │ ├── NoOp.java │ │ ├── OpcodesUtils.java │ │ ├── RelationalOperationBS.java │ │ ├── ThrowBS.java │ │ ├── UnboxBS.java │ │ ├── logicalop │ │ │ ├── CastBS.java │ │ │ ├── LogicalAndBS.java │ │ │ ├── LogicalNotBS.java │ │ │ └── LogicalOrBS.java │ │ ├── pushop │ │ │ ├── PushBoolean.java │ │ │ ├── PushDoubleConst.java │ │ │ ├── PushFloatConst.java │ │ │ ├── PushInstanceField.java │ │ │ ├── PushIntConst.java │ │ │ ├── PushLocalVar.java │ │ │ ├── PushLongConst.java │ │ │ ├── PushStaticField.java │ │ │ ├── PushStringConst.java │ │ │ └── PushThis.java │ │ └── returnop │ │ │ ├── ReturnFalseBS.java │ │ │ ├── ReturnTrueBS.java │ │ │ ├── ReturnValueBS.java │ │ │ └── ReturnVoidBS.java │ │ └── jvm │ │ ├── JvmConstructorDefinition.java │ │ ├── JvmFieldDefinition.java │ │ ├── JvmInvokableDefinition.java │ │ ├── JvmMethodDefinition.java │ │ ├── JvmNameUtils.java │ │ ├── JvmType.java │ │ └── JvmTypeCategory.java │ └── test │ └── java │ └── me │ └── tomassetti │ └── turin │ └── resolvers │ └── compiled │ └── JvmNameUtilsTest.java ├── dev-files └── eclipse-formatter.xml ├── documentation ├── .gitignore ├── Makefile ├── conf.py ├── functions.rst ├── imports.rst ├── index.rst ├── javadiff.rst ├── make.bat ├── namespace.rst ├── programs.rst ├── properties.rst ├── syntax.rst └── types.rst ├── pom.xml ├── run_asmifier.sh ├── samples └── ranma.to ├── turin-compiler ├── log.txt ├── log2.txt ├── pom.xml └── src │ ├── main │ └── java │ │ └── me │ │ └── tomassetti │ │ └── turin │ │ ├── classloading │ │ ├── ClassFileDefinition.java │ │ └── TurinClassLoader.java │ │ ├── compiler │ │ ├── AmbiguousCallException.java │ │ ├── BoxUnboxing.java │ │ ├── BytecodeUtils.java │ │ ├── Compilation.java │ │ ├── CompilationOfGeneratedMethods.java │ │ ├── CompilationOfPush.java │ │ ├── CompilationOfStatements.java │ │ ├── Compiler.java │ │ ├── LocalVarsSymbolTable.java │ │ ├── ParamUtils.java │ │ └── errorhandling │ │ │ ├── ErrorCollector.java │ │ │ └── SemanticErrorException.java │ │ ├── definitions │ │ ├── ContextDefinition.java │ │ ├── ExposedField.java │ │ ├── InternalConstructorDefinition.java │ │ ├── InternalInvokableDefinition.java │ │ ├── InternalMethodDefinition.java │ │ └── TypeDefinition.java │ │ ├── parser │ │ ├── ParseTreeToAst.java │ │ ├── Parser.java │ │ ├── TurinFileWithSource.java │ │ ├── analysis │ │ │ ├── Property.java │ │ │ └── exceptions │ │ │ │ ├── UnsolvedConstructorException.java │ │ │ │ ├── UnsolvedException.java │ │ │ │ ├── UnsolvedInvokableException.java │ │ │ │ ├── UnsolvedMethodException.java │ │ │ │ ├── UnsolvedSymbolException.java │ │ │ │ └── UnsolvedTypeException.java │ │ └── ast │ │ │ ├── FormalParameterNode.java │ │ │ ├── MethodSetAsInvokableType.java │ │ │ ├── Named.java │ │ │ ├── NamespaceDefinition.java │ │ │ ├── NoContext.java │ │ │ ├── Node.java │ │ │ ├── Placeholder.java │ │ │ ├── Point.java │ │ │ ├── Position.java │ │ │ ├── Program.java │ │ │ ├── QualifiedName.java │ │ │ ├── TurinFile.java │ │ │ ├── TurinTypeDefinition.java │ │ │ ├── TypeDefinitionNode.java │ │ │ ├── annotations │ │ │ └── AnnotationUsage.java │ │ │ ├── context │ │ │ └── ContextDefinitionNode.java │ │ │ ├── expressions │ │ │ ├── ActualParam.java │ │ │ ├── ArrayAccess.java │ │ │ ├── AssignmentExpression.java │ │ │ ├── ContextAccess.java │ │ │ ├── Creation.java │ │ │ ├── Expression.java │ │ │ ├── FieldAccess.java │ │ │ ├── FunctionCall.java │ │ │ ├── InstanceFieldAccess.java │ │ │ ├── InstanceMethodInvokation.java │ │ │ ├── InvokableExpr.java │ │ │ ├── LogicOperation.java │ │ │ ├── MathOperation.java │ │ │ ├── NotOperation.java │ │ │ ├── RelationSubset.java │ │ │ ├── RelationalOperation.java │ │ │ ├── SemanticError.java │ │ │ ├── StaticFieldAccess.java │ │ │ ├── StringInterpolation.java │ │ │ ├── ThisExpression.java │ │ │ ├── TypeIdentifier.java │ │ │ ├── ValueReference.java │ │ │ ├── literals │ │ │ │ ├── BooleanLiteral.java │ │ │ │ ├── ByteLiteral.java │ │ │ │ ├── DoubleLiteral.java │ │ │ │ ├── FloatLiteral.java │ │ │ │ ├── IntLiteral.java │ │ │ │ ├── LongLiteral.java │ │ │ │ ├── ShortLiteral.java │ │ │ │ └── StringLiteral.java │ │ │ └── relations │ │ │ │ └── AccessEndpoint.java │ │ │ ├── imports │ │ │ ├── AllFieldsImportDeclaration.java │ │ │ ├── AllPackageImportDeclaration.java │ │ │ ├── ImportDeclaration.java │ │ │ ├── SingleFieldImportDeclaration.java │ │ │ └── TypeImportDeclaration.java │ │ │ ├── invokables │ │ │ ├── FunctionDefinitionNode.java │ │ │ ├── InvokableDefinitionNode.java │ │ │ ├── TurinTypeContructorDefinitionNode.java │ │ │ └── TurinTypeMethodDefinitionNode.java │ │ │ ├── properties │ │ │ ├── PropertyConstraint.java │ │ │ ├── PropertyDefinition.java │ │ │ └── PropertyReference.java │ │ │ ├── relations │ │ │ ├── RelationDefinition.java │ │ │ └── RelationFieldDefinition.java │ │ │ ├── statements │ │ │ ├── BlockStatement.java │ │ │ ├── CatchClause.java │ │ │ ├── ContextAssignment.java │ │ │ ├── ContextScope.java │ │ │ ├── ElifClause.java │ │ │ ├── ExpressionStatement.java │ │ │ ├── IfStatement.java │ │ │ ├── ReturnStatement.java │ │ │ ├── Statement.java │ │ │ ├── SuperInvokation.java │ │ │ ├── ThrowStatement.java │ │ │ ├── TryCatchStatement.java │ │ │ └── VariableDeclaration.java │ │ │ ├── typeusage │ │ │ ├── ArrayTypeUsageNode.java │ │ │ ├── BasicTypeUsageNode.java │ │ │ ├── PrimitiveTypeUsageNode.java │ │ │ ├── ReferenceTypeUsageNode.java │ │ │ ├── TypeUsageNode.java │ │ │ ├── TypeUsageWrapperNode.java │ │ │ ├── TypeVariableTypeNode.java │ │ │ └── VoidTypeUsageNode.java │ │ │ └── virtual │ │ │ └── ArrayLength.java │ │ ├── resolvers │ │ ├── ComposedSymbolResolver.java │ │ ├── ComposedTypeResolver.java │ │ ├── InFileSymbolResolver.java │ │ ├── ResolverProvider.java │ │ ├── ResolverRegistry.java │ │ ├── SrcSymbolResolver.java │ │ ├── SymbolResolver.java │ │ ├── TypeResolver.java │ │ ├── compiled │ │ │ ├── AbstractCompiledTypeResolver.java │ │ │ ├── ClassPoolFactory.java │ │ │ ├── ClasspathElement.java │ │ │ ├── DirClassesClasspathElement.java │ │ │ ├── DirClassesTypeResolver.java │ │ │ ├── JarClasspathElement.java │ │ │ ├── JarTypeResolver.java │ │ │ ├── JavassistBasedMethodResolution.java │ │ │ ├── JavassistTypeDefinition.java │ │ │ ├── JavassistTypeDefinitionFactory.java │ │ │ └── LoadedFunctionDefinition.java │ │ └── jdk │ │ │ ├── JdkTypeResolver.java │ │ │ ├── ReflectionBasedField.java │ │ │ ├── ReflectionBasedMethodResolution.java │ │ │ ├── ReflectionBasedSetOfOverloadedMethods.java │ │ │ ├── ReflectionBasedTypeDefinition.java │ │ │ └── ReflectionTypeDefinitionFactory.java │ │ ├── symbols │ │ ├── FormalParameter.java │ │ ├── FormalParameterSymbol.java │ │ ├── InvokableDefinition.java │ │ └── Symbol.java │ │ ├── typesystem │ │ ├── ArrayTypeUsage.java │ │ ├── ConcreteTypeVariableUsage.java │ │ ├── Invokable.java │ │ ├── InvokableReferenceTypeUsage.java │ │ ├── MethodResolutionLogic.java │ │ ├── OverloadedFunctionReferenceTypeUsage.java │ │ ├── OverloadedInvokableReferenceTypeUsage.java │ │ ├── PrimitiveTypeUsage.java │ │ ├── ReferenceTypeUsage.java │ │ ├── TypeUsage.java │ │ ├── TypeVariableUsage.java │ │ ├── UnsignedPrimitiveTypeUsage.java │ │ └── VoidTypeUsage.java │ │ └── util │ │ ├── Either.java │ │ └── StringUtils.java │ └── test │ ├── java │ └── me │ │ └── tomassetti │ │ └── turin │ │ ├── compiler │ │ ├── AbstractCompilerTest.java │ │ ├── AdvancedExamplesCompilationTest.java │ │ ├── AnnotationCompilationTest.java │ │ ├── ArrayAccessCompilationTest.java │ │ ├── AsteriskParameterCompilationTest.java │ │ ├── BasicTypesTest.java │ │ ├── CompileArrayOperationsTest.java │ │ ├── CompilerJarReferenceTest.java │ │ ├── CompilerOnAstTest.java │ │ ├── CompilerOnFileTest.java │ │ ├── CompilerOnProgramTest.java │ │ ├── ConstructorsAndExtensionCompilationTest.java │ │ ├── DefaultValuesCompilationTest.java │ │ ├── DuplicateNamesCompilationTest.java │ │ ├── ExamplesAst.java │ │ ├── ExplicitConstructorsTest.java │ │ ├── ExtensionsCompilerTest.java │ │ ├── FieldConstraintsCompilationTest.java │ │ ├── FunctionsCompilationTest.java │ │ ├── ImportsTest.java │ │ ├── InitialValuesCompilationTest.java │ │ ├── LocalVarSymbolTableTest.java │ │ ├── ParamUtilsTest.java │ │ ├── ReferenceToCaughtExceptionCompilationTest.java │ │ ├── ReferenceToLocalVarCompilationTest.java │ │ ├── ReferenceToStaticFieldInCompiledClassCompilationTest.java │ │ ├── ReferencesInOtherSrcFileTest.java │ │ ├── StaticMethodsInvokationCompilationTest.java │ │ ├── ThrowCatchCompilationTest.java │ │ ├── TopLevelFunctionInvokationCompilationTest.java │ │ ├── context │ │ │ └── ContextCompilationTest.java │ │ └── relations │ │ │ └── RelationsCompilationTest.java │ │ ├── parser │ │ ├── ParseTreeToAstTest.java │ │ ├── analysis │ │ │ └── jar │ │ │ │ └── JarTypeResolverTest.java │ │ └── ast │ │ │ ├── QualifiedNameTest.java │ │ │ ├── TurinTypeDefinitionTest.java │ │ │ ├── TypeDefinitionTest.java │ │ │ ├── ValueReferenceTest.java │ │ │ ├── reflection │ │ │ ├── ReflectionBasedTypeDefinitionTest.java │ │ │ └── ReflectionTypeDefinitionFactoryTest.java │ │ │ └── typeusage │ │ │ ├── ReferenceTypeUsageTest.java │ │ │ └── TypeDefinitionTest.java │ │ ├── resolvers │ │ ├── SrcSymbolResolverTest.java │ │ └── compiled │ │ │ └── DirClassTypeResolverTest.java │ │ ├── typesystem │ │ ├── ArrayTypeUsageTest.java │ │ ├── InvokableReferenceTypeUsageTest.java │ │ ├── PrimitiveTypeUsageTest.java │ │ ├── UnsignedPrimitiveTypeUsageTest.java │ │ └── VoidTypeUsageTest.java │ │ └── util │ │ └── EitherTest.java │ └── resources │ ├── annotations.to │ ├── array_access.to │ ├── array_length.to │ ├── bad_usage_of_asterisk_on_creation1.to │ ├── bad_usage_of_asterisk_on_creation2.to │ ├── bad_usage_of_asterisk_on_creation3.to │ ├── bad_usage_of_asterisk_on_method1.to │ ├── basicManga.to │ ├── boolean_literals.to │ ├── call_void_function.to │ ├── common_methods.to │ ├── context │ ├── context_definition.to │ └── context_usage.to │ ├── default_values.to │ ├── duplicate_functions.to │ ├── duplicate_programs.to │ ├── duplicate_types.to │ ├── examples │ ├── formatter1.to │ ├── formatter2.to │ └── formatter3.to │ ├── explicit_constructor_no_extend.to │ ├── explicit_constructors.to │ ├── field_constraints_on_default_param.to │ ├── field_constraints_on_non_default_param.to │ ├── function_reference.to │ ├── function_with_block_body.to │ ├── function_with_expression_body.to │ ├── if.to │ ├── importOfAllFieldsInType.to │ ├── importOfAllFieldsInUnexistingType.to │ ├── importOfFieldsInTypeWithAlias.to │ ├── importOfFieldsInTypeWithoutAlias.to │ ├── importOfTypeWithAlias.to │ ├── importOfTypeWithoutAlias.to │ ├── importOfTypesFromUnexistingPackage.to │ ├── importOfTypesInPackage.to │ ├── importOfUnexistingField.to │ ├── importOfUnexistingType.to │ ├── import_date_with_alias.to │ ├── import_date_with_asterisk.to │ ├── import_date_without_asterisk.to │ ├── initial_values.to │ ├── instantiation_of_date.to │ ├── jars │ ├── javaparser-core-2.2.1.jar │ └── junit-4.12.jar │ ├── logical_operators.to │ ├── manga.to │ ├── manga_with_methods.to │ ├── math.to │ ├── ok_usage_of_asterisk_in_creation_with_object.to │ ├── ok_usage_of_asterisk_in_method_with_object.to │ ├── parser_examples │ └── type_extending_and_implementing.to │ ├── primitive_data.to │ ├── ranma.to │ ├── ref_to_function_in_classes.to │ ├── reference_to_caught_exception.to │ ├── reference_to_localvar.to │ ├── reference_to_static_field_compiled.to │ ├── relational_operators.to │ ├── relations │ ├── relation_subset.to │ ├── relation_usage.to │ └── simple_relation.to │ ├── scenarios │ ├── constructor_extends1 │ │ └── points.to │ ├── constructorinseparateclassdir │ │ ├── classdira │ │ │ └── foo.to │ │ └── classdirb │ │ │ └── foo_test.to │ ├── overloadresolution │ │ ├── foo.to │ │ └── foo_test.to │ ├── referencefunctionfromothersrcfile │ │ ├── foo.to │ │ └── foo_test.to │ ├── referencetoseparateclassdir │ │ ├── classdira │ │ │ └── foo.to │ │ └── classdirb │ │ │ └── foo_test.to │ └── referencetypefromothersrcfile │ │ ├── foo.to │ │ └── foo_test.to │ ├── static_methods_invokation.to │ ├── throw_statement.to │ ├── throw_statement_using_string.to │ ├── try_catch_statement.to │ ├── type_extending.to │ ├── type_implementing.to │ ├── ubyte_property.to │ ├── udouble_property.to │ ├── ufloat_property.to │ ├── uint_property.to │ ├── ulong_property.to │ ├── use_jar.to │ ├── use_jar_constructor.to │ ├── use_jar_method.to │ ├── use_jar_static_method.to │ └── ushort_property.to ├── turin-parser ├── pom.xml └── src │ ├── main │ ├── antlr4 │ │ └── me │ │ │ └── tomassetti │ │ │ └── parser │ │ │ └── antlr │ │ │ ├── TurinLexer.g4 │ │ │ └── TurinParser.g4 │ └── java │ │ └── me │ │ └── tomassetti │ │ └── turin │ │ └── parser │ │ └── InternalParser.java │ └── test │ ├── java │ └── me │ │ └── tomassetti │ │ └── parser │ │ └── antlr │ │ ├── TurinLexerTest.java │ │ └── TurinParserTest.java │ └── resources │ └── me │ └── tomassetti │ └── turin │ ├── args_length_different_from_one.to │ ├── context_definition.to │ ├── context_scope.to │ ├── context_usage.to │ ├── explicit_constructor.to │ ├── field_access.to │ ├── field_constraint.to │ ├── function_definitions_block.to │ ├── function_definitions_expression.to │ ├── imports_example.to │ ├── local_var.to │ ├── method_definitions_block.to │ ├── method_definitions_expression.to │ ├── method_invokation.to │ ├── relation_subset.to │ ├── simple_relation.to │ └── string_interp1.to ├── turin-standard-library ├── pom.xml └── src │ ├── main │ └── java │ │ └── turin │ │ ├── collections │ │ └── MapBuilder.java │ │ ├── compilation │ │ └── DefaultParam.java │ │ ├── context │ │ └── Context.java │ │ ├── relations │ │ ├── ManyToManyRelation.java │ │ ├── OneToManyRelation.java │ │ ├── OneToOneRelation.java │ │ ├── Relation.java │ │ └── Subset.java │ │ └── test │ │ └── Test.java │ └── test │ └── java │ └── turin │ ├── context │ └── ContextTest.java │ └── relations │ ├── Course.java │ ├── OneToManyRelationTest.java │ ├── Professor.java │ └── Teaching.java ├── update_coverage.sh └── walkmod.xml /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by .ignore support plugin (hsz.mobi) 2 | ### Java template 3 | *.class 4 | 5 | # Mobile Tools for Java (J2ME) 6 | .mtj.tmp/ 7 | 8 | # Package Files # 9 | *.jar 10 | *.war 11 | *.ear 12 | 13 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 14 | hs_err_pid* 15 | 16 | 17 | .idea 18 | *.iml 19 | target 20 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | language: java 3 | install: mvn install -DskipTests=true 4 | script: mvn test 5 | jdk: 6 | - oraclejdk8 7 | -------------------------------------------------------------------------------- /bytecode-generation/src/main/java/me/tomassetti/bytecode_generation/ArrayAccessBS.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.bytecode_generation; 2 | 3 | import me.tomassetti.jvm.JvmTypeCategory; 4 | import org.objectweb.asm.MethodVisitor; 5 | 6 | public class ArrayAccessBS extends BytecodeSequence { 7 | 8 | private JvmTypeCategory jvmTypeCategory; 9 | 10 | public ArrayAccessBS(JvmTypeCategory jvmTypeCategory) { 11 | this.jvmTypeCategory = jvmTypeCategory; 12 | } 13 | 14 | @Override 15 | public void operate(MethodVisitor mv) { 16 | mv.visitInsn(jvmTypeCategory.arrayLoadOpcode()); 17 | } 18 | 19 | } 20 | -------------------------------------------------------------------------------- /bytecode-generation/src/main/java/me/tomassetti/bytecode_generation/ArrayLengthBS.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.bytecode_generation; 2 | 3 | import org.objectweb.asm.MethodVisitor; 4 | import org.objectweb.asm.Opcodes; 5 | 6 | public class ArrayLengthBS extends BytecodeSequence { 7 | 8 | @Override 9 | public void operate(MethodVisitor mv) { 10 | mv.visitInsn(Opcodes.ARRAYLENGTH); 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /bytecode-generation/src/main/java/me/tomassetti/bytecode_generation/BytecodeSequence.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.bytecode_generation; 2 | 3 | import org.objectweb.asm.MethodVisitor; 4 | 5 | /** 6 | * A sequence of instructions to be performed inside of a method. 7 | */ 8 | public abstract class BytecodeSequence { 9 | 10 | public abstract void operate(MethodVisitor mv); 11 | 12 | } 13 | -------------------------------------------------------------------------------- /bytecode-generation/src/main/java/me/tomassetti/bytecode_generation/ComposedBytecodeSequence.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.bytecode_generation; 2 | 3 | import com.google.common.collect.ImmutableList; 4 | import org.objectweb.asm.MethodVisitor; 5 | 6 | import java.util.List; 7 | 8 | public class ComposedBytecodeSequence extends BytecodeSequence { 9 | 10 | private List components; 11 | 12 | public ComposedBytecodeSequence(BytecodeSequence... components) { 13 | this(ImmutableList.builder().add(components).build()); 14 | } 15 | 16 | public ComposedBytecodeSequence(List components) { 17 | this.components = components; 18 | } 19 | 20 | @Override 21 | public void operate(MethodVisitor mv) { 22 | for (BytecodeSequence component : components) { 23 | component.operate(mv); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /bytecode-generation/src/main/java/me/tomassetti/bytecode_generation/IntToLongBS.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.bytecode_generation; 2 | 3 | import org.objectweb.asm.MethodVisitor; 4 | import org.objectweb.asm.Opcodes; 5 | 6 | public class IntToLongBS extends BytecodeSequence { 7 | @Override 8 | public void operate(MethodVisitor mv) { 9 | mv.visitInsn(Opcodes.I2L); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /bytecode-generation/src/main/java/me/tomassetti/bytecode_generation/LocalVarAssignmentBS.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.bytecode_generation; 2 | 3 | import me.tomassetti.jvm.JvmTypeCategory; 4 | import org.objectweb.asm.MethodVisitor; 5 | 6 | public class LocalVarAssignmentBS extends BytecodeSequence { 7 | 8 | private int assignmentTarget; 9 | private JvmTypeCategory jvmTypeCategory; 10 | 11 | /** 12 | * @param assignmentTarget the local variable index of the value being assigned 13 | * @param jvmTypeCategory 14 | */ 15 | public LocalVarAssignmentBS(int assignmentTarget, JvmTypeCategory jvmTypeCategory) { 16 | if (assignmentTarget < 0) { 17 | throw new IllegalArgumentException(); 18 | } 19 | this.assignmentTarget = assignmentTarget; 20 | this.jvmTypeCategory = jvmTypeCategory; 21 | } 22 | 23 | @Override 24 | public void operate(MethodVisitor mv) { 25 | mv.visitVarInsn(jvmTypeCategory.storeOpcode(), assignmentTarget); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /bytecode-generation/src/main/java/me/tomassetti/bytecode_generation/MathOperationBS.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.bytecode_generation; 2 | 3 | import org.objectweb.asm.MethodVisitor; 4 | 5 | public class MathOperationBS extends BytecodeSequence { 6 | 7 | private int opcode; 8 | 9 | public MathOperationBS(int opcode) { 10 | this.opcode = opcode; 11 | } 12 | 13 | @Override 14 | public void operate(MethodVisitor mv) { 15 | mv.visitInsn(this.opcode); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /bytecode-generation/src/main/java/me/tomassetti/bytecode_generation/MethodInvocationBS.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.bytecode_generation; 2 | 3 | import me.tomassetti.jvm.JvmMethodDefinition; 4 | import org.objectweb.asm.MethodVisitor; 5 | 6 | import static org.objectweb.asm.Opcodes.*; 7 | 8 | public class MethodInvocationBS extends BytecodeSequence { 9 | 10 | private JvmMethodDefinition jvmMethodDefinition; 11 | 12 | public MethodInvocationBS(JvmMethodDefinition jvmMethodDefinition) { 13 | this.jvmMethodDefinition = jvmMethodDefinition; 14 | } 15 | 16 | @Override 17 | public void operate(MethodVisitor mv) { 18 | // The difference between the invokespecial and the invokevirtual instructions is that invokevirtual invokes 19 | // a method based on the class of the object. The invokespecial instruction is used to invoke instance 20 | // initialization methods as well as private methods and methods of a superclass of the current class. 21 | // ref.: http://zeroturnaround.com/rebellabs/java-bytecode-fundamentals-using-objects-and-calling-methods/ 22 | if (jvmMethodDefinition.isStatic()) { 23 | mv.visitMethodInsn(INVOKESTATIC, jvmMethodDefinition.getOwnerInternalName(), 24 | jvmMethodDefinition.getName(), jvmMethodDefinition.getDescriptor(), false); 25 | } else { 26 | if (jvmMethodDefinition.isDeclaredOnInterface()) { 27 | mv.visitMethodInsn(INVOKEINTERFACE, jvmMethodDefinition.getOwnerInternalName(), 28 | jvmMethodDefinition.getName(), jvmMethodDefinition.getDescriptor(), true); 29 | } else { 30 | mv.visitMethodInsn(INVOKEVIRTUAL, jvmMethodDefinition.getOwnerInternalName(), 31 | jvmMethodDefinition.getName(), jvmMethodDefinition.getDescriptor(), false); 32 | } 33 | } 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /bytecode-generation/src/main/java/me/tomassetti/bytecode_generation/NewInvocationBS.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.bytecode_generation; 2 | 3 | import me.tomassetti.jvm.JvmConstructorDefinition; 4 | import org.objectweb.asm.MethodVisitor; 5 | 6 | import static org.objectweb.asm.Opcodes.*; 7 | 8 | public class NewInvocationBS extends BytecodeSequence { 9 | 10 | private String type; 11 | private BytecodeSequence argumentsPush; 12 | private String descriptor; 13 | 14 | public NewInvocationBS(JvmConstructorDefinition constructorDefinition, BytecodeSequence argumentsPush) { 15 | this.type = constructorDefinition.getOwnerInternalName(); 16 | this.argumentsPush = argumentsPush; 17 | this.descriptor = constructorDefinition.getDescriptor(); 18 | } 19 | 20 | @Override 21 | public void operate(MethodVisitor mv) { 22 | mv.visitTypeInsn(NEW, type); 23 | // The first type is consumed by new, the second by the constructor 24 | mv.visitInsn(DUP); 25 | argumentsPush.operate(mv); 26 | // false because the method is not declared on an interface 27 | mv.visitMethodInsn(INVOKESPECIAL, type, "", descriptor, false); 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /bytecode-generation/src/main/java/me/tomassetti/bytecode_generation/NoOp.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.bytecode_generation; 2 | 3 | import org.objectweb.asm.MethodVisitor; 4 | 5 | /** 6 | * Placeholder to indicate that nothing needs to be done. 7 | */ 8 | public class NoOp extends BytecodeSequence { 9 | 10 | private static final NoOp INSTANCE = new NoOp(); 11 | 12 | private NoOp() { 13 | // prevent instantiation outside class 14 | } 15 | 16 | @Override 17 | public void operate(MethodVisitor mv) { 18 | // nothing to do 19 | } 20 | 21 | public static BytecodeSequence getInstance() { 22 | return INSTANCE; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /bytecode-generation/src/main/java/me/tomassetti/bytecode_generation/OpcodesUtils.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.bytecode_generation; 2 | 3 | import me.tomassetti.jvm.JvmType; 4 | 5 | import static org.objectweb.asm.Opcodes.*; 6 | import static org.objectweb.asm.Opcodes.ALOAD; 7 | 8 | public class OpcodesUtils { 9 | 10 | private OpcodesUtils() { 11 | // prevent instantiation 12 | } 13 | 14 | public static int returnTypeFor(JvmType jvmType) { 15 | switch (jvmType.getDescriptor()) { 16 | case "Z": 17 | case "B": 18 | case "S": 19 | case "C": 20 | case "I": 21 | // used for boolean, byte, short, char, or int 22 | return IRETURN; 23 | case "J": 24 | return LRETURN; 25 | case "F": 26 | return FRETURN; 27 | case "D": 28 | return DRETURN; 29 | case "V": 30 | return RETURN; 31 | default: 32 | return ARETURN; 33 | } 34 | } 35 | 36 | public static int loadTypeFor(JvmType jvmType) { 37 | switch (jvmType.getDescriptor()) { 38 | case "Z": 39 | case "B": 40 | case "S": 41 | case "C": 42 | case "I": 43 | // used for boolean, byte, short, char, or int 44 | return ILOAD; 45 | case "J": 46 | return LLOAD; 47 | case "F": 48 | return FLOAD; 49 | case "D": 50 | return DLOAD; 51 | default: 52 | return ALOAD; 53 | } 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /bytecode-generation/src/main/java/me/tomassetti/bytecode_generation/RelationalOperationBS.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.bytecode_generation; 2 | 3 | import org.objectweb.asm.Label; 4 | import org.objectweb.asm.MethodVisitor; 5 | import org.objectweb.asm.Opcodes; 6 | 7 | public class RelationalOperationBS extends BytecodeSequence { 8 | 9 | private int jumpOpcode; 10 | 11 | public RelationalOperationBS(int jumpOpcode) { 12 | this.jumpOpcode = jumpOpcode; 13 | } 14 | 15 | @Override 16 | public void operate(MethodVisitor mv) { 17 | Label l0 = new Label(); 18 | mv.visitJumpInsn(jumpOpcode, l0); 19 | mv.visitInsn(Opcodes.ICONST_1); 20 | Label l1 = new Label(); 21 | mv.visitJumpInsn(Opcodes.GOTO, l1); 22 | mv.visitLabel(l0); 23 | mv.visitInsn(Opcodes.ICONST_0); 24 | mv.visitLabel(l1); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /bytecode-generation/src/main/java/me/tomassetti/bytecode_generation/ThrowBS.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.bytecode_generation; 2 | 3 | import org.objectweb.asm.MethodVisitor; 4 | 5 | import static org.objectweb.asm.Opcodes.ATHROW; 6 | 7 | public class ThrowBS extends BytecodeSequence { 8 | 9 | private BytecodeSequence pushException; 10 | 11 | public ThrowBS(BytecodeSequence pushException) { 12 | this.pushException = pushException; 13 | } 14 | 15 | @Override 16 | public void operate(MethodVisitor mv) { 17 | pushException.operate(mv); 18 | mv.visitInsn(ATHROW); 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /bytecode-generation/src/main/java/me/tomassetti/bytecode_generation/UnboxBS.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.bytecode_generation; 2 | 3 | import me.tomassetti.jvm.JvmMethodDefinition; 4 | import me.tomassetti.jvm.JvmType; 5 | import org.objectweb.asm.MethodVisitor; 6 | 7 | /** 8 | * It expects the value to be already on the stack. 9 | */ 10 | public class UnboxBS extends BytecodeSequence { 11 | 12 | private JvmType jvmType; 13 | 14 | public UnboxBS(JvmType jvmType) { 15 | this.jvmType = jvmType; 16 | } 17 | 18 | @Override 19 | public void operate(MethodVisitor mv) { 20 | if (jvmType.equals(new JvmType("I"))) { 21 | new MethodInvocationBS(new JvmMethodDefinition("java/lang/Integer", "intValue", "()I", false, false)).operate(mv); 22 | } else if (jvmType.equals(new JvmType("Z"))) { 23 | new MethodInvocationBS(new JvmMethodDefinition("java/lang/Boolean", "booleanValue", "()Z", false, false)).operate(mv); 24 | } else if (jvmType.equals(new JvmType("C"))) { 25 | new MethodInvocationBS(new JvmMethodDefinition("java/lang/Character", "charValue", "()C", false, false)).operate(mv); 26 | } else if (jvmType.equals(new JvmType("B"))) { 27 | new MethodInvocationBS(new JvmMethodDefinition("java/lang/Byte", "byteValue", "()B", false, false)).operate(mv); 28 | } else if (jvmType.equals(new JvmType("S"))) { 29 | new MethodInvocationBS(new JvmMethodDefinition("java/lang/Short", "shortValue", "()S", false, false)).operate(mv); 30 | } else if (jvmType.equals(new JvmType("J"))) { 31 | new MethodInvocationBS(new JvmMethodDefinition("java/lang/Long", "longValue", "()J", false, false)).operate(mv); 32 | } else if (jvmType.equals(new JvmType("F"))) { 33 | new MethodInvocationBS(new JvmMethodDefinition("java/lang/Float", "floatValue", "()F", false, false)).operate(mv); 34 | } else if (jvmType.equals(new JvmType("D"))) { 35 | new MethodInvocationBS(new JvmMethodDefinition("java/lang/Double", "doubleValue", "()D", false, false)).operate(mv); 36 | } else { 37 | throw new UnsupportedOperationException(jvmType.toString()); 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /bytecode-generation/src/main/java/me/tomassetti/bytecode_generation/logicalop/CastBS.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.bytecode_generation.logicalop; 2 | 3 | import me.tomassetti.bytecode_generation.BytecodeSequence; 4 | import org.objectweb.asm.MethodVisitor; 5 | import org.objectweb.asm.Opcodes; 6 | 7 | public class CastBS extends BytecodeSequence { 8 | 9 | private String type; 10 | 11 | public CastBS(String type) { 12 | this.type = type; 13 | } 14 | 15 | @Override 16 | public void operate(MethodVisitor mv) { 17 | mv.visitTypeInsn(Opcodes.CHECKCAST, type); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /bytecode-generation/src/main/java/me/tomassetti/bytecode_generation/logicalop/LogicalAndBS.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.bytecode_generation.logicalop; 2 | 3 | import me.tomassetti.bytecode_generation.BytecodeSequence; 4 | import org.objectweb.asm.MethodVisitor; 5 | import org.objectweb.asm.Opcodes; 6 | 7 | public class LogicalAndBS extends BytecodeSequence { 8 | 9 | @Override 10 | public void operate(MethodVisitor mv) { 11 | mv.visitInsn(Opcodes.IAND); 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /bytecode-generation/src/main/java/me/tomassetti/bytecode_generation/logicalop/LogicalNotBS.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.bytecode_generation.logicalop; 2 | 3 | import me.tomassetti.bytecode_generation.BytecodeSequence; 4 | import org.objectweb.asm.Label; 5 | import org.objectweb.asm.MethodVisitor; 6 | import org.objectweb.asm.Opcodes; 7 | 8 | public class LogicalNotBS extends BytecodeSequence { 9 | 10 | private BytecodeSequence valueToNegate; 11 | 12 | public LogicalNotBS(BytecodeSequence valueToNegate) { 13 | this.valueToNegate = valueToNegate; 14 | } 15 | 16 | public LogicalNotBS() { 17 | this.valueToNegate = null; 18 | } 19 | 20 | @Override 21 | 22 | public void operate(MethodVisitor mv) { 23 | if (valueToNegate != null) { 24 | valueToNegate.operate(mv); 25 | } 26 | // it is very weird that there is not a single instruction for this... 27 | Label l0 = new Label(); 28 | mv.visitJumpInsn(Opcodes.IFNE, l0); 29 | mv.visitInsn(Opcodes.ICONST_1); 30 | Label l1 = new Label(); 31 | mv.visitJumpInsn(Opcodes.GOTO, l1); 32 | mv.visitLabel(l0); 33 | mv.visitInsn(Opcodes.ICONST_0); 34 | mv.visitLabel(l1); 35 | } 36 | 37 | } 38 | -------------------------------------------------------------------------------- /bytecode-generation/src/main/java/me/tomassetti/bytecode_generation/logicalop/LogicalOrBS.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.bytecode_generation.logicalop; 2 | 3 | import me.tomassetti.bytecode_generation.BytecodeSequence; 4 | import org.objectweb.asm.MethodVisitor; 5 | import org.objectweb.asm.Opcodes; 6 | 7 | public class LogicalOrBS extends BytecodeSequence { 8 | 9 | @Override 10 | public void operate(MethodVisitor mv) { 11 | mv.visitInsn(Opcodes.IOR); 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /bytecode-generation/src/main/java/me/tomassetti/bytecode_generation/pushop/PushBoolean.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.bytecode_generation.pushop; 2 | 3 | import me.tomassetti.bytecode_generation.BytecodeSequence; 4 | import org.objectweb.asm.MethodVisitor; 5 | import org.objectweb.asm.Opcodes; 6 | 7 | public class PushBoolean extends BytecodeSequence { 8 | 9 | private boolean value; 10 | 11 | public PushBoolean(boolean value) { 12 | this.value = value; 13 | } 14 | 15 | @Override 16 | public void operate(MethodVisitor mv) { 17 | if (value) { 18 | mv.visitInsn(Opcodes.ICONST_1); 19 | } else { 20 | mv.visitInsn(Opcodes.ICONST_0); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /bytecode-generation/src/main/java/me/tomassetti/bytecode_generation/pushop/PushDoubleConst.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.bytecode_generation.pushop; 2 | 3 | import me.tomassetti.bytecode_generation.BytecodeSequence; 4 | import org.objectweb.asm.MethodVisitor; 5 | 6 | /** 7 | * Put a direct value in the stack. 8 | */ 9 | public class PushDoubleConst extends BytecodeSequence { 10 | 11 | private double value; 12 | 13 | public PushDoubleConst(double value) { 14 | this.value = value; 15 | } 16 | 17 | @Override 18 | public void operate(MethodVisitor mv) { 19 | mv.visitLdcInsn(value); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /bytecode-generation/src/main/java/me/tomassetti/bytecode_generation/pushop/PushFloatConst.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.bytecode_generation.pushop; 2 | 3 | import me.tomassetti.bytecode_generation.BytecodeSequence; 4 | import org.objectweb.asm.MethodVisitor; 5 | 6 | /** 7 | * Put a direct value in the stack. 8 | */ 9 | public class PushFloatConst extends BytecodeSequence { 10 | 11 | private float value; 12 | 13 | public PushFloatConst(float value) { 14 | this.value = value; 15 | } 16 | 17 | @Override 18 | public void operate(MethodVisitor mv) { 19 | mv.visitLdcInsn(value); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /bytecode-generation/src/main/java/me/tomassetti/bytecode_generation/pushop/PushInstanceField.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.bytecode_generation.pushop; 2 | 3 | import me.tomassetti.bytecode_generation.BytecodeSequence; 4 | import me.tomassetti.jvm.JvmFieldDefinition; 5 | import org.objectweb.asm.MethodVisitor; 6 | 7 | import static org.objectweb.asm.Opcodes.GETFIELD; 8 | 9 | public class PushInstanceField extends BytecodeSequence { 10 | 11 | private JvmFieldDefinition fieldDefinition; 12 | private boolean pushThis; 13 | 14 | public PushInstanceField(JvmFieldDefinition fieldDefinition, boolean pushThis) { 15 | this.fieldDefinition = fieldDefinition; 16 | this.pushThis = pushThis; 17 | } 18 | 19 | public PushInstanceField(JvmFieldDefinition fieldDefinition) { 20 | this(fieldDefinition, true); 21 | } 22 | 23 | @Override 24 | public void operate(MethodVisitor mv) { 25 | if (fieldDefinition.isStatic()) { 26 | throw new UnsupportedOperationException(); 27 | } else { 28 | if (pushThis) { 29 | PushThis.getInstance().operate(mv); 30 | } 31 | mv.visitFieldInsn(GETFIELD, fieldDefinition.getOwnerInternalName(), fieldDefinition.getFieldName(), fieldDefinition.getDescriptor()); 32 | } 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /bytecode-generation/src/main/java/me/tomassetti/bytecode_generation/pushop/PushIntConst.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.bytecode_generation.pushop; 2 | 3 | import me.tomassetti.bytecode_generation.BytecodeSequence; 4 | import org.objectweb.asm.MethodVisitor; 5 | import org.objectweb.asm.Opcodes; 6 | 7 | /** 8 | * Put a direct value in the stack expanding it to an int. 9 | */ 10 | public class PushIntConst extends BytecodeSequence { 11 | 12 | private int value; 13 | private int operation; 14 | private boolean useLdcInsn; 15 | 16 | public PushIntConst(int value) { 17 | if (value < Short.MIN_VALUE || value > Short.MAX_VALUE) { 18 | useLdcInsn = true; 19 | } else { 20 | useLdcInsn = false; 21 | if (value < Byte.MIN_VALUE || value > Byte.MAX_VALUE) { 22 | this.operation = Opcodes.SIPUSH; 23 | } else { 24 | this.operation = Opcodes.BIPUSH; 25 | } 26 | } 27 | this.value = value; 28 | } 29 | 30 | @Override 31 | public void operate(MethodVisitor mv) { 32 | if (useLdcInsn) { 33 | mv.visitLdcInsn(new Integer(value)); 34 | } else { 35 | mv.visitIntInsn(operation, value); 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /bytecode-generation/src/main/java/me/tomassetti/bytecode_generation/pushop/PushLocalVar.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.bytecode_generation.pushop; 2 | 3 | import me.tomassetti.bytecode_generation.BytecodeSequence; 4 | import org.objectweb.asm.MethodVisitor; 5 | 6 | /** 7 | * Push a local variable in the stack. 8 | */ 9 | public class PushLocalVar extends BytecodeSequence { 10 | 11 | private int loadType; 12 | private int index; 13 | 14 | public PushLocalVar(int loadType, int index) { 15 | this.loadType = loadType; 16 | this.index = index; 17 | } 18 | 19 | @Override 20 | public void operate(MethodVisitor mv) { 21 | mv.visitVarInsn(loadType, index); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /bytecode-generation/src/main/java/me/tomassetti/bytecode_generation/pushop/PushLongConst.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.bytecode_generation.pushop; 2 | 3 | import me.tomassetti.bytecode_generation.BytecodeSequence; 4 | import org.objectweb.asm.MethodVisitor; 5 | import org.objectweb.asm.Opcodes; 6 | 7 | /** 8 | * Put a direct value in the stack. 9 | */ 10 | public class PushLongConst extends BytecodeSequence { 11 | 12 | private long value; 13 | 14 | public PushLongConst(long value) { 15 | this.value = value; 16 | } 17 | 18 | @Override 19 | public void operate(MethodVisitor mv) { 20 | mv.visitLdcInsn(value); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /bytecode-generation/src/main/java/me/tomassetti/bytecode_generation/pushop/PushStaticField.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.bytecode_generation.pushop; 2 | 3 | import me.tomassetti.bytecode_generation.BytecodeSequence; 4 | import me.tomassetti.jvm.JvmFieldDefinition; 5 | import org.objectweb.asm.MethodVisitor; 6 | 7 | import static org.objectweb.asm.Opcodes.*; 8 | 9 | public class PushStaticField extends BytecodeSequence { 10 | 11 | private JvmFieldDefinition fieldDefinition; 12 | 13 | public PushStaticField(JvmFieldDefinition fieldDefinition) { 14 | this.fieldDefinition = fieldDefinition; 15 | } 16 | 17 | @Override 18 | public void operate(MethodVisitor mv) { 19 | if (fieldDefinition.isStatic()) { 20 | mv.visitFieldInsn(GETSTATIC, fieldDefinition.getOwnerInternalName(), fieldDefinition.getFieldName(), fieldDefinition.getDescriptor()); 21 | } else { 22 | throw new UnsupportedOperationException(); 23 | } 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /bytecode-generation/src/main/java/me/tomassetti/bytecode_generation/pushop/PushStringConst.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.bytecode_generation.pushop; 2 | 3 | import me.tomassetti.bytecode_generation.BytecodeSequence; 4 | import org.objectweb.asm.MethodVisitor; 5 | 6 | /** 7 | * Push a String into the stack. 8 | */ 9 | public class PushStringConst extends BytecodeSequence { 10 | 11 | private String value; 12 | 13 | public PushStringConst(String value) { 14 | this.value = value; 15 | } 16 | 17 | @Override 18 | public void operate(MethodVisitor mv) { 19 | mv.visitLdcInsn(value); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /bytecode-generation/src/main/java/me/tomassetti/bytecode_generation/pushop/PushThis.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.bytecode_generation.pushop; 2 | 3 | import me.tomassetti.bytecode_generation.BytecodeSequence; 4 | import org.objectweb.asm.MethodVisitor; 5 | 6 | import static org.objectweb.asm.Opcodes.ALOAD; 7 | 8 | /** 9 | * Push the "this" value in the stack. 10 | */ 11 | public class PushThis extends BytecodeSequence { 12 | 13 | public static final int LOCALVAR_INDEX_FOR_THIS_IN_METHOD = 0; 14 | 15 | private static PushThis INSTANCE = new PushThis(); 16 | 17 | private PushThis() { 18 | 19 | } 20 | 21 | public static PushThis getInstance() { 22 | return INSTANCE; 23 | } 24 | 25 | @Override 26 | public void operate(MethodVisitor mv) { 27 | mv.visitVarInsn(ALOAD, LOCALVAR_INDEX_FOR_THIS_IN_METHOD); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /bytecode-generation/src/main/java/me/tomassetti/bytecode_generation/returnop/ReturnFalseBS.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.bytecode_generation.returnop; 2 | 3 | import me.tomassetti.bytecode_generation.BytecodeSequence; 4 | import org.objectweb.asm.MethodVisitor; 5 | 6 | import static org.objectweb.asm.Opcodes.ICONST_0; 7 | import static org.objectweb.asm.Opcodes.IRETURN; 8 | 9 | public class ReturnFalseBS extends BytecodeSequence { 10 | 11 | @Override 12 | public void operate(MethodVisitor mv) { 13 | mv.visitInsn(ICONST_0); 14 | mv.visitInsn(IRETURN); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /bytecode-generation/src/main/java/me/tomassetti/bytecode_generation/returnop/ReturnTrueBS.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.bytecode_generation.returnop; 2 | 3 | import me.tomassetti.bytecode_generation.BytecodeSequence; 4 | import org.objectweb.asm.MethodVisitor; 5 | 6 | import static org.objectweb.asm.Opcodes.ICONST_1; 7 | import static org.objectweb.asm.Opcodes.IRETURN; 8 | 9 | public class ReturnTrueBS extends BytecodeSequence { 10 | 11 | @Override 12 | public void operate(MethodVisitor mv) { 13 | mv.visitInsn(ICONST_1); 14 | mv.visitInsn(IRETURN); 15 | } 16 | 17 | } 18 | -------------------------------------------------------------------------------- /bytecode-generation/src/main/java/me/tomassetti/bytecode_generation/returnop/ReturnValueBS.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.bytecode_generation.returnop; 2 | 3 | import me.tomassetti.bytecode_generation.BytecodeSequence; 4 | import org.objectweb.asm.MethodVisitor; 5 | 6 | public class ReturnValueBS extends BytecodeSequence { 7 | 8 | private int returnType; 9 | private BytecodeSequence pushValue; 10 | 11 | public ReturnValueBS(int returnType, BytecodeSequence pushValue) { 12 | this.returnType = returnType; 13 | this.pushValue = pushValue; 14 | } 15 | 16 | @Override 17 | public void operate(MethodVisitor mv) { 18 | pushValue.operate(mv); 19 | mv.visitInsn(returnType); 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /bytecode-generation/src/main/java/me/tomassetti/bytecode_generation/returnop/ReturnVoidBS.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.bytecode_generation.returnop; 2 | 3 | import me.tomassetti.bytecode_generation.BytecodeSequence; 4 | import org.objectweb.asm.MethodVisitor; 5 | import org.objectweb.asm.Opcodes; 6 | 7 | public class ReturnVoidBS extends BytecodeSequence { 8 | 9 | @Override 10 | public void operate(MethodVisitor mv) { 11 | mv.visitInsn(Opcodes.RETURN); 12 | } 13 | 14 | } 15 | -------------------------------------------------------------------------------- /bytecode-generation/src/main/java/me/tomassetti/jvm/JvmConstructorDefinition.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.jvm; 2 | 3 | public class JvmConstructorDefinition extends JvmInvokableDefinition { 4 | 5 | public JvmConstructorDefinition(String ownerInternalName, String descriptor) { 6 | super(ownerInternalName, "", descriptor); 7 | } 8 | 9 | @Override 10 | public boolean equals(Object o) { 11 | if (this == o) return true; 12 | if (!(o instanceof JvmConstructorDefinition)) return false; 13 | 14 | JvmConstructorDefinition that = (JvmConstructorDefinition) o; 15 | 16 | if (!ownerInternalName.equals(that.ownerInternalName)) return false; 17 | if (!name.equals(that.name)) return false; 18 | if (!descriptor.equals(that.descriptor)) return false; 19 | 20 | return true; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /bytecode-generation/src/main/java/me/tomassetti/jvm/JvmFieldDefinition.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.jvm; 2 | 3 | public class JvmFieldDefinition { 4 | private String ownerInternalName; 5 | private String fieldName; 6 | private String descriptor; 7 | 8 | public String getOwnerInternalName() { 9 | return ownerInternalName; 10 | } 11 | 12 | public String getFieldName() { 13 | return fieldName; 14 | } 15 | 16 | public String getDescriptor() { 17 | return descriptor; 18 | } 19 | 20 | public boolean isStatic() { 21 | return static_; 22 | } 23 | 24 | private boolean static_; 25 | 26 | public JvmFieldDefinition(String ownerInternalName, String fieldName, String descriptor, boolean static_) { 27 | this.ownerInternalName = ownerInternalName; 28 | this.fieldName = fieldName; 29 | this.descriptor = descriptor; 30 | this.static_ = static_; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /bytecode-generation/src/main/java/me/tomassetti/jvm/JvmMethodDefinition.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.jvm; 2 | 3 | public class JvmMethodDefinition extends JvmInvokableDefinition { 4 | 5 | private boolean _static; 6 | private boolean declaredOnInterface; 7 | 8 | public JvmMethodDefinition(String ownerInternalName, String methodName, String descriptor, boolean _static, boolean declaredOnInterface) { 9 | super(ownerInternalName, methodName, descriptor); 10 | this._static = _static; 11 | this.declaredOnInterface = declaredOnInterface; 12 | } 13 | 14 | public boolean isStatic() { 15 | return _static; 16 | } 17 | 18 | public boolean isDeclaredOnInterface() { 19 | return declaredOnInterface; 20 | } 21 | 22 | @Override 23 | public boolean equals(Object o) { 24 | if (this == o) return true; 25 | if (!(o instanceof JvmMethodDefinition)) return false; 26 | 27 | JvmMethodDefinition that = (JvmMethodDefinition) o; 28 | 29 | if (_static != that._static) return false; 30 | if (declaredOnInterface != that.declaredOnInterface) return false; 31 | if (!ownerInternalName.equals(that.ownerInternalName)) return false; 32 | if (!name.equals(that.name)) return false; 33 | if (!descriptor.equals(that.descriptor)) return false; 34 | 35 | return true; 36 | } 37 | 38 | @Override 39 | public int hashCode() { 40 | int result = (_static ? 1 : 0); 41 | result = 31 * result + (declaredOnInterface ? 1 : 0); 42 | return result; 43 | } 44 | 45 | @Override 46 | public String toString() { 47 | return "JvmMethodDefinition{" + 48 | "_static=" + _static + 49 | ", declaredOnInterface=" + declaredOnInterface + 50 | '}'; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /bytecode-generation/src/main/java/me/tomassetti/jvm/JvmTypeCategory.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.jvm; 2 | 3 | import org.objectweb.asm.Opcodes; 4 | 5 | public enum JvmTypeCategory { 6 | INT, 7 | LONG, 8 | FLOAT, 9 | DOUBLE, 10 | REFERENCE, 11 | ARRAY; 12 | 13 | public int storeOpcode(){ 14 | switch (this){ 15 | case INT: 16 | return Opcodes.ISTORE; 17 | case LONG: 18 | return Opcodes.LSTORE; 19 | case FLOAT: 20 | return Opcodes.FSTORE; 21 | case DOUBLE: 22 | return Opcodes.DSTORE; 23 | case REFERENCE: 24 | return Opcodes.ASTORE; 25 | case ARRAY: 26 | return Opcodes.ASTORE; 27 | default: 28 | throw new UnsupportedOperationException(); 29 | } 30 | } 31 | 32 | public int arrayLoadOpcode(){ 33 | switch (this){ 34 | case INT: 35 | return Opcodes.IALOAD; 36 | case LONG: 37 | return Opcodes.LALOAD; 38 | case FLOAT: 39 | return Opcodes.FALOAD; 40 | case DOUBLE: 41 | return Opcodes.DALOAD; 42 | case REFERENCE: 43 | return Opcodes.AALOAD; 44 | default: 45 | throw new UnsupportedOperationException(); 46 | } 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /documentation/.gitignore: -------------------------------------------------------------------------------- 1 | _build 2 | -------------------------------------------------------------------------------- /documentation/functions.rst: -------------------------------------------------------------------------------- 1 | Functions 2 | ========= 3 | 4 | Body expression 5 | ~~~~~~~~~~~~~~~ 6 | 7 | :: 8 | 9 | int sum(int a, int b) = a + b 10 | -------------------------------------------------------------------------------- /documentation/imports.rst: -------------------------------------------------------------------------------- 1 | Imports 2 | ------- 3 | 4 | There are four different variants of imports: the first two are very similar to classic imports you have in Java, while 5 | the second are similar to the static imports, just a bit more flexible. 6 | 7 | Import of a type 8 | ~~~~~~~~~~~~~~~~ 9 | 10 | This is very similar to Java, except for the missing semicolon: :: 11 | 12 | import java.util.Collections 13 | 14 | Differently from Java it is possible to define an alias: :: 15 | 16 | import java.util.Collections as Coll 17 | 18 | Import of all types in a package 19 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 20 | 21 | Import all types in a package, like in Java: 22 | 23 | import java.util.* 24 | 25 | Import single element 26 | ~~~~~~~~~~~~~~~~~~~~~ 27 | 28 | A few examples: :: 29 | 30 | import java.lang.System.out 31 | import java.lang.System.out.println 32 | import java.lang.System.out.println as print 33 | 34 | Import all elements 35 | ~~~~~~~~~~~~~~~~~~~ 36 | 37 | A few examples: :: 38 | 39 | import java.lang.System.* 40 | import java.lang.System.out.* 41 | 42 | -------------------------------------------------------------------------------- /documentation/index.rst: -------------------------------------------------------------------------------- 1 | Turin Programming Language's documentation 2 | ========================================== 3 | 4 | Turin is intended to be a pragmatic language which leverages all the benefits of the JVM while trying to be more clear, 5 | powerful and less redundant than Java. 6 | 7 | Getting started 8 | --------------- 9 | 10 | Turin is intended to be similar to Java in many respects. The philosophy is to introduce differences when an improvement 11 | can be made. For other things we stick to the Java approach. 12 | 13 | A few general things that are different are: 14 | 15 | * newlines are meaningful: similarly to Python you cannot insert a newline everywhere in the code 16 | * value and type identifiers are different: in Java classes tend to start with a capital letters while variable and 17 | parameter names tend to start with a lowercase letter. However this is not enforced by the language and the parser 18 | cannot take advantage from it. In Turin this is enforced instead. It is still possible to use Java types with a lower 19 | case letter or Java values with a capital letter by using escaping sequences. 20 | 21 | Differences w.r.t. Java 22 | ======================= 23 | 24 | In this section we examine more in details differences between Turin and Java. 25 | 26 | .. toctree:: 27 | :maxdepth: 2 28 | 29 | javadiff 30 | 31 | Syntax 32 | ====== 33 | 34 | Here we describe step by step the Turin syntax. 35 | 36 | .. toctree:: 37 | :maxdepth: 2 38 | 39 | namespace 40 | imports 41 | functions 42 | properties 43 | types 44 | programs 45 | 46 | 47 | -------------------------------------------------------------------------------- /documentation/namespace.rst: -------------------------------------------------------------------------------- 1 | Namespace 2 | --------- 3 | 4 | Here we talk about namespaces -------------------------------------------------------------------------------- /documentation/programs.rst: -------------------------------------------------------------------------------- 1 | Programs 2 | -------- 3 | 4 | Define programs. -------------------------------------------------------------------------------- /documentation/properties.rst: -------------------------------------------------------------------------------- 1 | Properties 2 | ---------- -------------------------------------------------------------------------------- /documentation/syntax.rst: -------------------------------------------------------------------------------- 1 | Syntax 2 | ====== 3 | 4 | .. toctree:: 5 | :maxdepth: 2 6 | 7 | namespace 8 | imports 9 | functions 10 | properties 11 | types 12 | programs 13 | -------------------------------------------------------------------------------- /run_asmifier.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | java -classpath "/home/federico/.m2/repository/org/ow2/asm/asm/5.0.4/asm-5.0.4.jar:/home/federico/.m2/repository/org/ow2/asm/asm-util/5.0.4/asm-util-5.0.4.jar:/home/federico/.m2/repository/org/ow2/asm/asm-tree/5.0.4/asm-tree-5.0.4.jar" org.objectweb.asm.util.ASMifier turin-compiler/target/classes/me/tomassetti/turin/parser/ast/expressions/Creation.class -------------------------------------------------------------------------------- /samples/ranma.to: -------------------------------------------------------------------------------- 1 | namespace manga 2 | 3 | import java.lang.System.out.println as print 4 | 5 | property String : name 6 | 7 | type MangaCharacter { 8 | has name 9 | has UInt : age 10 | } 11 | 12 | program MangaExample(String[] args) { 13 | val ranma = MangaCharacter("Ranma", 16) 14 | print("The protagonist is #{ranma}") 15 | //print("The protagonist is " + ranma.name) 16 | } 17 | -------------------------------------------------------------------------------- /turin-compiler/src/main/java/me/tomassetti/turin/classloading/ClassFileDefinition.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.turin.classloading; 2 | 3 | /** 4 | * Elements necessary to define a class file. 5 | */ 6 | public class ClassFileDefinition { 7 | 8 | private String name; 9 | private byte[] bytecode; 10 | 11 | public String getName() { 12 | return name; 13 | } 14 | 15 | public byte[] getBytecode() { 16 | return bytecode; 17 | } 18 | 19 | public ClassFileDefinition(String name, byte[] bytecode) { 20 | if (name.contains("/")) { 21 | throw new IllegalArgumentException(); 22 | } 23 | this.name = name; 24 | this.bytecode = bytecode; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /turin-compiler/src/main/java/me/tomassetti/turin/classloading/TurinClassLoader.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.turin.classloading; 2 | 3 | import me.tomassetti.jvm.JvmNameUtils; 4 | 5 | /** 6 | * ClassLoader used to load classes compiled from Turin. 7 | */ 8 | public class TurinClassLoader extends ClassLoader { 9 | 10 | public Class addClass(ClassFileDefinition classFileDefinition){ 11 | return addClass(classFileDefinition.getName(), classFileDefinition.getBytecode()); 12 | } 13 | 14 | public Class addClass(String name, byte[] bytecode){ 15 | if (!JvmNameUtils.isValidQualifiedName(name)) { 16 | throw new IllegalArgumentException(); 17 | } 18 | return defineClass(name, bytecode, 0, bytecode.length); 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /turin-compiler/src/main/java/me/tomassetti/turin/compiler/AmbiguousCallException.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.turin.compiler; 2 | 3 | import me.tomassetti.jvm.JvmType; 4 | import me.tomassetti.turin.parser.ast.Node; 5 | import me.tomassetti.turin.parser.ast.expressions.ActualParam; 6 | 7 | import java.util.List; 8 | 9 | /** 10 | * A call is ambiguous: we are not able to differentiate between various overloaded methods to invoke. 11 | */ 12 | public class AmbiguousCallException extends RuntimeException { 13 | 14 | private Node context; 15 | private String name; 16 | private List actualParamTypes; 17 | private List actualParams; 18 | 19 | public AmbiguousCallException(Node context, List actualParams, String name) { 20 | this.context = context; 21 | this.actualParams = actualParams; 22 | this.name = name; 23 | } 24 | 25 | public AmbiguousCallException(Node context, String name, List actualParamTypes) { 26 | this.context = context; 27 | this.name = name; 28 | this.actualParamTypes = actualParamTypes; 29 | } 30 | 31 | public Node getContext() { 32 | return context; 33 | } 34 | 35 | public String getName() { 36 | return name; 37 | } 38 | 39 | public List getActualParamTypes() { 40 | return actualParamTypes; 41 | } 42 | 43 | public List getActualParams() { 44 | return actualParams; 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /turin-compiler/src/main/java/me/tomassetti/turin/compiler/errorhandling/ErrorCollector.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.turin.compiler.errorhandling; 2 | 3 | import me.tomassetti.turin.parser.ast.Position; 4 | 5 | public interface ErrorCollector { 6 | 7 | void recordSemanticError(Position position, String description); 8 | 9 | } 10 | -------------------------------------------------------------------------------- /turin-compiler/src/main/java/me/tomassetti/turin/compiler/errorhandling/SemanticErrorException.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.turin.compiler.errorhandling; 2 | 3 | import me.tomassetti.turin.parser.ast.Node; 4 | 5 | public class SemanticErrorException extends RuntimeException { 6 | private Node node; 7 | private String description; 8 | 9 | public Node getNode() { 10 | return node; 11 | } 12 | 13 | @Override 14 | public boolean equals(Object o) { 15 | if (this == o) return true; 16 | if (o == null || getClass() != o.getClass()) return false; 17 | 18 | SemanticErrorException that = (SemanticErrorException) o; 19 | 20 | if (!description.equals(that.description)) return false; 21 | if (!node.equals(that.node)) return false; 22 | 23 | return true; 24 | } 25 | 26 | @Override 27 | public int hashCode() { 28 | int result = node.hashCode(); 29 | result = 31 * result + description.hashCode(); 30 | return result; 31 | } 32 | 33 | @Override 34 | public String toString() { 35 | return "SemanticErrorException{" + 36 | "node=" + node + 37 | ", description='" + description + '\'' + 38 | '}'; 39 | } 40 | 41 | public String getDescription() { 42 | return description; 43 | } 44 | 45 | public SemanticErrorException(Node node, String description) { 46 | this.node = node; 47 | this.description = description; 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /turin-compiler/src/main/java/me/tomassetti/turin/definitions/ContextDefinition.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.turin.definitions; 2 | 3 | import me.tomassetti.turin.typesystem.TypeUsage; 4 | 5 | public interface ContextDefinition { 6 | String getName(); 7 | TypeUsage getType(); 8 | 9 | String getClassQualifiedName(); 10 | 11 | String getQualifiedName(); 12 | } 13 | -------------------------------------------------------------------------------- /turin-compiler/src/main/java/me/tomassetti/turin/definitions/ExposedField.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.turin.definitions; 2 | 3 | import me.tomassetti.turin.typesystem.TypeUsage; 4 | 5 | /** 6 | * Something which can be accessed as it was a field. 7 | * It could be a real field or things like Class.class, array.length, or relations endpoints. 8 | */ 9 | public interface ExposedField { 10 | boolean accessibleStatically(); 11 | boolean accessibleOnInstance(); 12 | boolean canBeAssigned(); 13 | String name(); 14 | TypeUsage type(); 15 | } 16 | -------------------------------------------------------------------------------- /turin-compiler/src/main/java/me/tomassetti/turin/parser/Parser.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.turin.parser; 2 | 3 | import com.google.common.collect.ImmutableList; 4 | import me.tomassetti.parser.antlr.TurinLexer; 5 | import me.tomassetti.turin.parser.ast.TurinFile; 6 | 7 | import java.io.File; 8 | import java.io.FileInputStream; 9 | import java.io.IOException; 10 | import java.io.InputStream; 11 | import java.util.ArrayList; 12 | import java.util.List; 13 | 14 | /** 15 | * Produce ASTs from the source code. 16 | */ 17 | public class Parser { 18 | 19 | private InternalParser internalParser = new InternalParser(); 20 | 21 | public TurinFile parse(InputStream inputStream) throws IOException { 22 | return new ParseTreeToAst().toAst(internalParser.produceParseTree(inputStream)); 23 | } 24 | 25 | /** 26 | * Accept a file or a directory. If a directory is given all the children are recursively parsed. 27 | * All files are parsed, irrespectively of their extension. 28 | */ 29 | public List parseAllIn(File file) throws IOException { 30 | if (file.isFile()) { 31 | return ImmutableList.of(new TurinFileWithSource(file, parse(new FileInputStream(file)))); 32 | } else if (file.isDirectory()) { 33 | List result = new ArrayList<>(); 34 | for (File child : file.listFiles()) { 35 | result.addAll(parseAllIn(child)); 36 | } 37 | return result; 38 | } else { 39 | throw new IllegalArgumentException("Neither a file or a directory: " + file.getPath()); 40 | } 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /turin-compiler/src/main/java/me/tomassetti/turin/parser/TurinFileWithSource.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.turin.parser; 2 | 3 | import me.tomassetti.turin.parser.ast.TurinFile; 4 | 5 | import java.io.File; 6 | 7 | /** 8 | * Represent a pair of a compiled TurinFile and the File from which it was obtained. 9 | */ 10 | public class TurinFileWithSource { 11 | private File source; 12 | private TurinFile turinFile; 13 | 14 | public TurinFileWithSource(File source, TurinFile turinFile) { 15 | this.source = source; 16 | this.turinFile = turinFile; 17 | } 18 | 19 | public File getSource() { 20 | return source; 21 | } 22 | 23 | public TurinFile getTurinFile() { 24 | return turinFile; 25 | } 26 | 27 | @Override 28 | public boolean equals(Object o) { 29 | if (this == o) return true; 30 | if (o == null || getClass() != o.getClass()) return false; 31 | 32 | TurinFileWithSource that = (TurinFileWithSource) o; 33 | 34 | if (!source.equals(that.source)) return false; 35 | if (!turinFile.equals(that.turinFile)) return false; 36 | 37 | return true; 38 | } 39 | 40 | @Override 41 | public int hashCode() { 42 | int result = source.hashCode(); 43 | result = 31 * result + turinFile.hashCode(); 44 | return result; 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /turin-compiler/src/main/java/me/tomassetti/turin/parser/analysis/exceptions/UnsolvedConstructorException.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.turin.parser.analysis.exceptions; 2 | 3 | import me.tomassetti.turin.parser.ast.expressions.ActualParam; 4 | 5 | import java.util.List; 6 | 7 | public class UnsolvedConstructorException extends UnsolvedException { 8 | 9 | private String typeCanonicalName; 10 | private List paramList; 11 | 12 | public UnsolvedConstructorException(String typeCanonicalName, List paramList) { 13 | super("Unsolved constructor for " + typeCanonicalName + " with params " + paramList); 14 | this.typeCanonicalName = typeCanonicalName; 15 | this.paramList = paramList; 16 | } 17 | 18 | public UnsolvedConstructorException(String typeCanonicalName, List paramList, String detail) { 19 | super("Unsolved constructor for " + typeCanonicalName + " with params " + paramList + ": " + detail); 20 | this.typeCanonicalName = typeCanonicalName; 21 | this.paramList = paramList; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /turin-compiler/src/main/java/me/tomassetti/turin/parser/analysis/exceptions/UnsolvedException.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.turin.parser.analysis.exceptions; 2 | 3 | public abstract class UnsolvedException extends RuntimeException { 4 | 5 | public UnsolvedException(String message) { 6 | super(message); 7 | } 8 | 9 | } 10 | -------------------------------------------------------------------------------- /turin-compiler/src/main/java/me/tomassetti/turin/parser/analysis/exceptions/UnsolvedInvokableException.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.turin.parser.analysis.exceptions; 2 | 3 | import me.tomassetti.turin.parser.ast.expressions.InvokableExpr; 4 | 5 | public class UnsolvedInvokableException extends UnsolvedException { 6 | 7 | public UnsolvedInvokableException(InvokableExpr invokable) { 8 | super("Unsolved invokable call " + invokable.toString()); 9 | } 10 | 11 | } 12 | -------------------------------------------------------------------------------- /turin-compiler/src/main/java/me/tomassetti/turin/parser/analysis/exceptions/UnsolvedMethodException.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.turin.parser.analysis.exceptions; 2 | 3 | import me.tomassetti.turin.parser.ast.expressions.ActualParam; 4 | import me.tomassetti.turin.parser.ast.expressions.FunctionCall; 5 | import me.tomassetti.turin.parser.ast.statements.SuperInvokation; 6 | 7 | import java.util.List; 8 | 9 | public class UnsolvedMethodException extends UnsolvedException { 10 | 11 | public UnsolvedMethodException(FunctionCall functionCall) { 12 | super("Unsolved function call " + functionCall.toString()); 13 | } 14 | 15 | public UnsolvedMethodException(String qualifiedName, String methodName, List actualParams) { 16 | super("Unsolved method " + methodName); 17 | // TODO improve 18 | } 19 | 20 | public UnsolvedMethodException(SuperInvokation superInvokation) { 21 | super("Unsolved super invokation " + superInvokation); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /turin-compiler/src/main/java/me/tomassetti/turin/parser/analysis/exceptions/UnsolvedSymbolException.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.turin.parser.analysis.exceptions; 2 | 3 | import me.tomassetti.turin.parser.ast.Node; 4 | 5 | /** 6 | * Some symbol of some sort has not being solved. 7 | */ 8 | public class UnsolvedSymbolException extends UnsolvedException { 9 | 10 | private Node node; 11 | 12 | public UnsolvedSymbolException(Node node) { 13 | super("Unsolved " + node); 14 | this.node = node; 15 | } 16 | 17 | public UnsolvedSymbolException(String fieldName) { 18 | super("Unsolved " + fieldName); 19 | } 20 | 21 | public UnsolvedSymbolException(Node context, String typeName) { 22 | super("Unsolved symbol "+ typeName + " in "+context.describe()); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /turin-compiler/src/main/java/me/tomassetti/turin/parser/analysis/exceptions/UnsolvedTypeException.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.turin.parser.analysis.exceptions; 2 | 3 | import me.tomassetti.turin.parser.ast.Node; 4 | 5 | public class UnsolvedTypeException extends UnsolvedException { 6 | 7 | public UnsolvedTypeException(String typeName, Node context) { 8 | super("type " + typeName + " not solved in " + context); 9 | } 10 | 11 | } 12 | -------------------------------------------------------------------------------- /turin-compiler/src/main/java/me/tomassetti/turin/parser/ast/MethodSetAsInvokableType.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.turin.parser.ast; 2 | 3 | import me.tomassetti.turin.definitions.InternalMethodDefinition; 4 | import me.tomassetti.turin.parser.ast.expressions.ActualParam; 5 | import me.tomassetti.turin.typesystem.Invokable; 6 | import me.tomassetti.turin.typesystem.MethodResolutionLogic; 7 | import me.tomassetti.turin.typesystem.TypeUsage; 8 | 9 | import java.util.*; 10 | 11 | public class MethodSetAsInvokableType implements Invokable { 12 | private Set methodDefinitions; 13 | private Map typeParams; 14 | 15 | public MethodSetAsInvokableType(Set methodDefinitions, Map typeParams) { 16 | this.methodDefinitions = methodDefinitions; 17 | this.typeParams = typeParams; 18 | } 19 | 20 | @Override 21 | public boolean isOverloaded() { 22 | return methodDefinitions.size() > 1; 23 | } 24 | 25 | @Override 26 | public Optional internalInvokableDefinitionFor(List actualParams) { 27 | Optional method = MethodResolutionLogic.findMethodAmongActualParams(actualParams, new ArrayList<>(methodDefinitions)); 28 | method = method.map((imd)->imd.apply(typeParams)); 29 | return method; 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /turin-compiler/src/main/java/me/tomassetti/turin/parser/ast/Named.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.turin.parser.ast; 2 | 3 | public interface Named { 4 | String getName(); 5 | } 6 | -------------------------------------------------------------------------------- /turin-compiler/src/main/java/me/tomassetti/turin/parser/ast/NamespaceDefinition.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.turin.parser.ast; 2 | 3 | import com.google.common.collect.ImmutableList; 4 | import me.tomassetti.jvm.JvmNameUtils; 5 | 6 | public class NamespaceDefinition extends Node { 7 | 8 | private String name; 9 | 10 | public NamespaceDefinition(String name) { 11 | if (!JvmNameUtils.isValidQualifiedName(name)) { 12 | throw new IllegalArgumentException(name); 13 | } 14 | this.name = name; 15 | } 16 | 17 | public String getName() { 18 | return name; 19 | } 20 | 21 | @Override 22 | public Iterable getChildren() { 23 | return ImmutableList.of(); 24 | } 25 | 26 | @Override 27 | public String toString() { 28 | return "NamespaceDefinition{" + 29 | "name='" + name + '\'' + 30 | '}'; 31 | } 32 | 33 | @Override 34 | public boolean equals(Object o) { 35 | if (this == o) return true; 36 | if (o == null || getClass() != o.getClass()) return false; 37 | 38 | NamespaceDefinition that = (NamespaceDefinition) o; 39 | 40 | if (!name.equals(that.name)) return false; 41 | 42 | return true; 43 | } 44 | 45 | @Override 46 | public int hashCode() { 47 | return name.hashCode(); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /turin-compiler/src/main/java/me/tomassetti/turin/parser/ast/NoContext.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.turin.parser.ast; 2 | 3 | import java.util.Collections; 4 | 5 | /** 6 | * Represent the absolute context, so it knows only about canonical names. 7 | */ 8 | public class NoContext extends Node { 9 | 10 | private static NoContext INSTANCE = new NoContext(); 11 | 12 | public static NoContext getInstance() { 13 | return INSTANCE; 14 | } 15 | 16 | private NoContext() { 17 | 18 | } 19 | 20 | @Override 21 | public Iterable getChildren() { 22 | return Collections.emptyList(); 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /turin-compiler/src/main/java/me/tomassetti/turin/parser/ast/Placeholder.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.turin.parser.ast; 2 | 3 | import me.tomassetti.turin.parser.ast.expressions.Expression; 4 | import me.tomassetti.turin.parser.ast.properties.PropertyDefinition; 5 | import me.tomassetti.turin.parser.ast.typeusage.TypeUsageNode; 6 | 7 | import java.util.Collections; 8 | 9 | public class Placeholder extends Expression { 10 | 11 | @Override 12 | public Iterable getChildren() { 13 | return Collections.emptyList(); 14 | } 15 | 16 | @Override 17 | public TypeUsageNode calcType() { 18 | Node parent = getParent(); 19 | while (parent != null) { 20 | if (parent instanceof PropertyDefinition) { 21 | PropertyDefinition propertyDefinition = (PropertyDefinition)parent; 22 | return propertyDefinition.getType(); 23 | } 24 | parent = parent.getParent(); 25 | } 26 | throw new IllegalStateException(); 27 | } 28 | 29 | 30 | } 31 | -------------------------------------------------------------------------------- /turin-compiler/src/main/java/me/tomassetti/turin/parser/ast/Point.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.turin.parser.ast; 2 | 3 | public class Point { 4 | private int line; 5 | private int column; 6 | 7 | public int getLine() { 8 | return line; 9 | } 10 | 11 | @Override 12 | public boolean equals(Object o) { 13 | if (this == o) return true; 14 | if (o == null || getClass() != o.getClass()) return false; 15 | 16 | Point point = (Point) o; 17 | 18 | if (column != point.column) return false; 19 | if (line != point.line) return false; 20 | 21 | return true; 22 | } 23 | 24 | @Override 25 | public String toString() { 26 | return "line " + line + ", col " + column; 27 | } 28 | 29 | @Override 30 | public int hashCode() { 31 | int result = line; 32 | result = 31 * result + column; 33 | return result; 34 | } 35 | 36 | public Point(int line, int column) { 37 | this.line = line; 38 | this.column = column; 39 | 40 | } 41 | 42 | public int getColumn() { 43 | return column; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /turin-compiler/src/main/java/me/tomassetti/turin/parser/ast/Position.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.turin.parser.ast; 2 | 3 | /** 4 | * The position of a Node in the source file. 5 | */ 6 | public class Position { 7 | 8 | private Point start; 9 | private Point end; 10 | 11 | @Override 12 | public String toString() { 13 | return "at " + start + " - " + end; 14 | } 15 | 16 | @Override 17 | public boolean equals(Object o) { 18 | if (this == o) return true; 19 | if (o == null || getClass() != o.getClass()) return false; 20 | 21 | Position position = (Position) o; 22 | 23 | if (!end.equals(position.end)) return false; 24 | if (!start.equals(position.start)) return false; 25 | 26 | return true; 27 | } 28 | 29 | @Override 30 | public int hashCode() { 31 | int result = start.hashCode(); 32 | result = 31 * result + end.hashCode(); 33 | return result; 34 | } 35 | 36 | public Point getStart() { 37 | return start; 38 | } 39 | 40 | public Point getEnd() { 41 | return end; 42 | } 43 | 44 | public Position(Point start, Point end) { 45 | this.start = start; 46 | this.end = end; 47 | } 48 | 49 | public static Position create(int startLine, int startCol, int endLine, int endCol) { 50 | return new Position(new Point(startLine, startCol), new Point(endLine, endCol)); 51 | } 52 | 53 | } 54 | -------------------------------------------------------------------------------- /turin-compiler/src/main/java/me/tomassetti/turin/parser/ast/annotations/AnnotationUsage.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.turin.parser.ast.annotations; 2 | 3 | import com.google.common.collect.ImmutableList; 4 | import me.tomassetti.jvm.JvmNameUtils; 5 | import me.tomassetti.turin.definitions.TypeDefinition; 6 | import me.tomassetti.turin.parser.analysis.exceptions.UnsolvedTypeException; 7 | import me.tomassetti.turin.resolvers.SymbolResolver; 8 | import me.tomassetti.turin.parser.ast.Node; 9 | 10 | import java.util.Optional; 11 | 12 | public class AnnotationUsage extends Node { 13 | 14 | private String name; 15 | 16 | public AnnotationUsage(String name) { 17 | this.name = name; 18 | } 19 | 20 | public String getName() { 21 | return name; 22 | } 23 | 24 | @Override 25 | public String toString() { 26 | return "AnnotationUsage{" + 27 | "name='" + name + '\'' + 28 | '}'; 29 | } 30 | 31 | @Override 32 | public Iterable getChildren() { 33 | return ImmutableList.of(); 34 | } 35 | 36 | public String getDescriptor(SymbolResolver resolver) { 37 | Optional type = resolver.findTypeDefinitionIn(name, this, resolver); 38 | if (!type.isPresent()) { 39 | throw new UnsolvedTypeException(name, this); 40 | } 41 | String qName = type.get().getQualifiedName(); 42 | return "L" + JvmNameUtils.canonicalToInternal(qName) + ";"; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /turin-compiler/src/main/java/me/tomassetti/turin/parser/ast/context/ContextDefinitionNode.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.turin.parser.ast.context; 2 | 3 | import com.google.common.collect.ImmutableList; 4 | import me.tomassetti.turin.definitions.ContextDefinition; 5 | import me.tomassetti.turin.parser.ast.Node; 6 | import me.tomassetti.turin.parser.ast.typeusage.TypeUsageNode; 7 | 8 | public class ContextDefinitionNode extends Node implements ContextDefinition { 9 | 10 | public static final String CLASS_PREFIX = "Context_"; 11 | private String name; 12 | private TypeUsageNode type; 13 | 14 | public ContextDefinitionNode(String name, TypeUsageNode type) { 15 | this.name = name; 16 | this.type = type; 17 | this.type.setParent(this); 18 | } 19 | 20 | @Override 21 | public String toString() { 22 | return "ContextDefinitionNode{" + 23 | "name='" + name + '\'' + 24 | ", type=" + type + 25 | '}'; 26 | } 27 | 28 | @Override 29 | public Iterable getChildren() { 30 | return ImmutableList.of(type); 31 | } 32 | 33 | public TypeUsageNode getType() { 34 | return type; 35 | } 36 | 37 | public String getName() { 38 | return name; 39 | } 40 | 41 | public String getClassQualifiedName() { 42 | return contextName() + "." + CLASS_PREFIX + name; 43 | } 44 | 45 | public String getQualifiedName() { 46 | return contextName() + "." + name; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /turin-compiler/src/main/java/me/tomassetti/turin/parser/ast/expressions/ArrayAccess.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.turin.parser.ast.expressions; 2 | 3 | import com.google.common.collect.ImmutableList; 4 | import me.tomassetti.turin.parser.ast.Node; 5 | import me.tomassetti.turin.typesystem.TypeUsage; 6 | 7 | public class ArrayAccess extends Expression { 8 | 9 | private Expression array; 10 | private Expression index; 11 | 12 | public Expression getArray() { 13 | return array; 14 | } 15 | 16 | public Expression getIndex() { 17 | return index; 18 | } 19 | 20 | public ArrayAccess(Expression array, Expression index) { 21 | this.array = array; 22 | this.array.setParent(this); 23 | this.index = index; 24 | 25 | this.index.setParent(this); 26 | } 27 | 28 | @Override 29 | public Iterable getChildren() { 30 | return ImmutableList.of(array, index); 31 | } 32 | 33 | @Override 34 | public TypeUsage calcType() { 35 | TypeUsage arrayType = array.calcType(); 36 | if (arrayType.isArray()) { 37 | return arrayType.asArrayTypeUsage().getComponentType(); 38 | } else { 39 | throw new UnsupportedOperationException(); 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /turin-compiler/src/main/java/me/tomassetti/turin/parser/ast/expressions/AssignmentExpression.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.turin.parser.ast.expressions; 2 | 3 | import com.google.common.collect.ImmutableList; 4 | import me.tomassetti.turin.compiler.errorhandling.ErrorCollector; 5 | import me.tomassetti.turin.resolvers.SymbolResolver; 6 | import me.tomassetti.turin.parser.ast.Node; 7 | import me.tomassetti.turin.typesystem.TypeUsage; 8 | 9 | public class AssignmentExpression extends Expression { 10 | 11 | private Expression target; 12 | private Expression value; 13 | 14 | @Override 15 | public String toString() { 16 | return "AssignmentStatement{" + 17 | "target=" + target + 18 | ", value=" + value + 19 | '}'; 20 | } 21 | 22 | public AssignmentExpression(Expression target, Expression value) { 23 | this.target = target; 24 | this.target.setParent(this); 25 | this.value = value; 26 | this.value.setParent(this); 27 | } 28 | 29 | @Override 30 | protected boolean specificValidate(SymbolResolver resolver, ErrorCollector errorCollector) { 31 | if (!this.target.canBeAssigned(resolver)) { 32 | errorCollector.recordSemanticError(this.target.getPosition(), "Cannot be assigned"); 33 | return false; 34 | } 35 | 36 | return super.specificValidate(resolver, errorCollector); 37 | } 38 | 39 | public Expression getTarget() { 40 | return target; 41 | } 42 | 43 | public Expression getValue() { 44 | return value; 45 | } 46 | 47 | @Override 48 | public Iterable getChildren() { 49 | return ImmutableList.of(target, value); 50 | } 51 | 52 | @Override 53 | public TypeUsage calcType() { 54 | return getTarget().calcType(); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /turin-compiler/src/main/java/me/tomassetti/turin/parser/ast/expressions/ContextAccess.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.turin.parser.ast.expressions; 2 | 3 | import com.google.common.collect.ImmutableList; 4 | import me.tomassetti.turin.compiler.errorhandling.ErrorCollector; 5 | import me.tomassetti.turin.definitions.ContextDefinition; 6 | import me.tomassetti.turin.parser.ast.Node; 7 | import me.tomassetti.turin.resolvers.SymbolResolver; 8 | import me.tomassetti.turin.resolvers.jdk.ReflectionTypeDefinitionFactory; 9 | import me.tomassetti.turin.symbols.Symbol; 10 | import me.tomassetti.turin.typesystem.ReferenceTypeUsage; 11 | import me.tomassetti.turin.typesystem.TypeUsage; 12 | 13 | import java.util.Collections; 14 | import java.util.Optional; 15 | 16 | public class ContextAccess extends Expression { 17 | 18 | private String contextName; 19 | private Optional contextSymbol; 20 | 21 | public ContextAccess(String contextName) { 22 | this.contextName = contextName; 23 | } 24 | 25 | @Override 26 | public Iterable getChildren() { 27 | return Collections.emptyList(); 28 | } 29 | 30 | public Optional contextSymbol() { 31 | if (contextSymbol == null) { 32 | contextSymbol = symbolResolver().findContextSymbol(contextName, this); 33 | } 34 | return contextSymbol; 35 | } 36 | 37 | @Override 38 | protected boolean specificValidate(SymbolResolver resolver, ErrorCollector errorCollector) { 39 | Optional contextSymbolOptional = resolver.findContextSymbol(contextName, this); 40 | if (!contextSymbolOptional.isPresent()) { 41 | errorCollector.recordSemanticError(getPosition(), "Context "+ contextName + " cannot be resolved"); 42 | return false; 43 | } 44 | return super.specificValidate(resolver, errorCollector); 45 | } 46 | 47 | @Override 48 | public TypeUsage calcType() { 49 | return new ReferenceTypeUsage( 50 | ReflectionTypeDefinitionFactory.getInstance().getTypeDefinition(Optional.class, symbolResolver()), 51 | ImmutableList.of(contextSymbol().get().getType())); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /turin-compiler/src/main/java/me/tomassetti/turin/parser/ast/expressions/Expression.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.turin.parser.ast.expressions; 2 | 3 | import me.tomassetti.jvm.JvmMethodDefinition; 4 | import me.tomassetti.jvm.JvmType; 5 | import me.tomassetti.turin.resolvers.SymbolResolver; 6 | import me.tomassetti.turin.parser.ast.Node; 7 | import me.tomassetti.turin.typesystem.TypeUsage; 8 | 9 | import java.util.List; 10 | 11 | public abstract class Expression extends Node { 12 | public abstract TypeUsage calcType(); 13 | 14 | /** 15 | * When the expression corresponds to something invokable this method find which Jvm method corresponds to the call 16 | * with the given parameters. 17 | */ 18 | public JvmMethodDefinition findMethodFor(List argsTypes, SymbolResolver resolver, boolean staticContext) { 19 | throw new UnsupportedOperationException("On " + this.getClass().getCanonicalName()); 20 | } 21 | 22 | /** 23 | * This expression represents a type? 24 | */ 25 | public boolean isType(SymbolResolver resolver) { 26 | return false; 27 | } 28 | 29 | public boolean canBeAssigned(SymbolResolver resolver) { 30 | return false; 31 | } 32 | 33 | public boolean canFieldBeAssigned(String field, SymbolResolver resolver) { 34 | throw new UnsupportedOperationException(this.getClass().getCanonicalName()); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /turin-compiler/src/main/java/me/tomassetti/turin/parser/ast/expressions/LogicOperation.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.turin.parser.ast.expressions; 2 | 3 | import com.google.common.collect.ImmutableList; 4 | import me.tomassetti.turin.parser.ast.Node; 5 | import me.tomassetti.turin.typesystem.PrimitiveTypeUsage; 6 | import me.tomassetti.turin.typesystem.TypeUsage; 7 | 8 | public class LogicOperation extends Expression { 9 | private Expression left; 10 | private Expression right; 11 | private Operator operator; 12 | 13 | @Override 14 | public Iterable getChildren() { 15 | return ImmutableList.of(left, right); 16 | } 17 | 18 | @Override 19 | public TypeUsage calcType() { 20 | return PrimitiveTypeUsage.BOOLEAN; 21 | } 22 | 23 | public Expression getLeft() { 24 | return left; 25 | } 26 | 27 | public Expression getRight() { 28 | return right; 29 | } 30 | 31 | public Operator getOperator() { 32 | return operator; 33 | } 34 | 35 | public enum Operator { 36 | AND("and"), 37 | OR("or"); 38 | 39 | private String symbol; 40 | 41 | private Operator(String symbol) { 42 | this.symbol = symbol; 43 | } 44 | 45 | public static Operator fromSymbol(String symbol) { 46 | for (Operator operator : Operator.values()) { 47 | if (operator.symbol.equals(symbol)) { 48 | return operator; 49 | } 50 | } 51 | throw new IllegalArgumentException(symbol); 52 | } 53 | } 54 | 55 | public LogicOperation(Operator operator, Expression left, Expression right) { 56 | this.operator = operator; 57 | this.left = left; 58 | this.left.setParent(this); 59 | this.right = right; 60 | this.right.setParent(this); 61 | } 62 | 63 | } 64 | -------------------------------------------------------------------------------- /turin-compiler/src/main/java/me/tomassetti/turin/parser/ast/expressions/MathOperation.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.turin.parser.ast.expressions; 2 | 3 | import com.google.common.collect.ImmutableList; 4 | import me.tomassetti.turin.parser.ast.Node; 5 | import me.tomassetti.turin.typesystem.TypeUsage; 6 | 7 | public class MathOperation extends Expression { 8 | private Expression left; 9 | private Expression right; 10 | private Operator operator; 11 | 12 | @Override 13 | public Iterable getChildren() { 14 | return ImmutableList.of(left, right); 15 | } 16 | 17 | @Override 18 | public TypeUsage calcType() { 19 | return left.calcType(); 20 | } 21 | 22 | public Expression getLeft() { 23 | return left; 24 | } 25 | 26 | public Expression getRight() { 27 | return right; 28 | } 29 | 30 | public Operator getOperator() { 31 | return operator; 32 | } 33 | 34 | public enum Operator { 35 | MULTIPLICATION("*"), 36 | DIVISION("/"), 37 | SUM("+"), 38 | SUBTRACTION("-"); 39 | 40 | private String symbol; 41 | 42 | private Operator(String symbol) { 43 | this.symbol = symbol; 44 | } 45 | 46 | public static Operator fromSymbol(String symbol) { 47 | for (Operator operator : Operator.values()) { 48 | if (operator.symbol.equals(symbol)) { 49 | return operator; 50 | } 51 | } 52 | throw new IllegalArgumentException(symbol); 53 | } 54 | } 55 | 56 | public MathOperation(Operator operator, Expression left, Expression right) { 57 | this.operator = operator; 58 | this.left = left; 59 | this.left.setParent(this); 60 | this.right = right; 61 | this.right.setParent(this); 62 | } 63 | 64 | } 65 | -------------------------------------------------------------------------------- /turin-compiler/src/main/java/me/tomassetti/turin/parser/ast/expressions/NotOperation.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.turin.parser.ast.expressions; 2 | 3 | import com.google.common.collect.ImmutableList; 4 | import me.tomassetti.turin.parser.ast.Node; 5 | import me.tomassetti.turin.typesystem.PrimitiveTypeUsage; 6 | import me.tomassetti.turin.typesystem.TypeUsage; 7 | 8 | public class NotOperation extends Expression { 9 | private Expression value; 10 | 11 | @Override 12 | public Iterable getChildren() { 13 | return ImmutableList.of(value); 14 | } 15 | 16 | @Override 17 | public TypeUsage calcType() { 18 | return PrimitiveTypeUsage.BOOLEAN; 19 | } 20 | 21 | public Expression getValue() { 22 | return value; 23 | } 24 | 25 | public NotOperation(Expression value) { 26 | this.value = value; 27 | this.value.setParent(this); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /turin-compiler/src/main/java/me/tomassetti/turin/parser/ast/expressions/RelationSubset.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.turin.parser.ast.expressions; 2 | 3 | import com.google.common.collect.ImmutableList; 4 | import me.tomassetti.turin.parser.ast.Node; 5 | import me.tomassetti.turin.parser.ast.typeusage.TypeUsageNode; 6 | 7 | import java.util.List; 8 | 9 | public class RelationSubset extends Expression { 10 | 11 | private String relationName; 12 | private String fieldName; 13 | private List matchingConditions; 14 | 15 | public RelationSubset(String relationName, String fieldName, List matchingConditions) { 16 | this.relationName = relationName; 17 | this.fieldName = fieldName; 18 | this.matchingConditions = matchingConditions; 19 | this.matchingConditions.forEach((mc) -> mc.setParent(RelationSubset.this)); 20 | } 21 | 22 | @Override 23 | public Iterable getChildren() { 24 | return ImmutableList.copyOf(matchingConditions); 25 | } 26 | 27 | @Override 28 | public TypeUsageNode calcType() { 29 | throw new UnsupportedOperationException(); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /turin-compiler/src/main/java/me/tomassetti/turin/parser/ast/expressions/RelationalOperation.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.turin.parser.ast.expressions; 2 | 3 | import com.google.common.collect.ImmutableList; 4 | import me.tomassetti.turin.parser.ast.Node; 5 | import me.tomassetti.turin.typesystem.PrimitiveTypeUsage; 6 | import me.tomassetti.turin.typesystem.TypeUsage; 7 | 8 | public class RelationalOperation extends Expression { 9 | private Expression left; 10 | private Expression right; 11 | private Operator operator; 12 | 13 | @Override 14 | public String toString() { 15 | return "RelationalOperation{" + 16 | "left=" + left + 17 | ", right=" + right + 18 | ", operator=" + operator + 19 | '}'; 20 | } 21 | 22 | @Override 23 | public Iterable getChildren() { 24 | return ImmutableList.of(left, right); 25 | } 26 | 27 | @Override 28 | public TypeUsage calcType() { 29 | return PrimitiveTypeUsage.BOOLEAN; 30 | } 31 | 32 | public Expression getLeft() { 33 | return left; 34 | } 35 | 36 | public Expression getRight() { 37 | return right; 38 | } 39 | 40 | public Operator getOperator() { 41 | return operator; 42 | } 43 | 44 | public enum Operator { 45 | EQUAL("=="), 46 | DIFFERENT("!="), 47 | LESS("<"), 48 | LESSEQ("<="), 49 | MORE(">"), 50 | MOREEQ(">="); 51 | 52 | private String symbol; 53 | 54 | private Operator(String symbol) { 55 | this.symbol = symbol; 56 | } 57 | 58 | public static Operator fromSymbol(String symbol) { 59 | for (Operator operator : Operator.values()) { 60 | if (operator.symbol.equals(symbol)) { 61 | return operator; 62 | } 63 | } 64 | throw new IllegalArgumentException(symbol); 65 | } 66 | } 67 | 68 | public RelationalOperation(Operator operator, Expression left, Expression right) { 69 | this.operator = operator; 70 | this.left = left; 71 | this.left.setParent(this); 72 | this.right = right; 73 | this.right.setParent(this); 74 | } 75 | 76 | } 77 | -------------------------------------------------------------------------------- /turin-compiler/src/main/java/me/tomassetti/turin/parser/ast/expressions/SemanticError.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.turin.parser.ast.expressions; 2 | 3 | import me.tomassetti.turin.compiler.errorhandling.ErrorCollector; 4 | import me.tomassetti.turin.resolvers.SymbolResolver; 5 | import me.tomassetti.turin.parser.ast.Node; 6 | import me.tomassetti.turin.parser.ast.Position; 7 | import me.tomassetti.turin.parser.ast.typeusage.TypeUsageNode; 8 | 9 | import java.util.Collections; 10 | 11 | public class SemanticError extends Expression { 12 | 13 | private String message; 14 | private Position position; 15 | 16 | @Override 17 | protected boolean specificValidate(SymbolResolver resolver, ErrorCollector errorCollector) { 18 | errorCollector.recordSemanticError(position, message); 19 | return false; 20 | } 21 | 22 | public SemanticError(String message, Position position) { 23 | this.message = message; 24 | this.position = position; 25 | } 26 | 27 | @Override 28 | public Iterable getChildren() { 29 | return Collections.emptyList(); 30 | } 31 | 32 | @Override 33 | public TypeUsageNode calcType() { 34 | throw new UnsupportedOperationException(); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /turin-compiler/src/main/java/me/tomassetti/turin/parser/ast/expressions/StringInterpolation.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.turin.parser.ast.expressions; 2 | 3 | import com.google.common.collect.ImmutableList; 4 | import me.tomassetti.turin.parser.ast.Node; 5 | import me.tomassetti.turin.typesystem.ReferenceTypeUsage; 6 | import me.tomassetti.turin.typesystem.TypeUsage; 7 | 8 | import java.util.ArrayList; 9 | import java.util.List; 10 | 11 | public class StringInterpolation extends Expression { 12 | 13 | private List elements = new ArrayList<>(); 14 | 15 | public List getElements() { 16 | return elements; 17 | } 18 | 19 | @Override 20 | public boolean equals(Object o) { 21 | if (this == o) return true; 22 | if (o == null || getClass() != o.getClass()) return false; 23 | 24 | StringInterpolation that = (StringInterpolation) o; 25 | 26 | if (!elements.equals(that.elements)) return false; 27 | 28 | return true; 29 | 30 | } 31 | 32 | @Override 33 | public int hashCode() { 34 | return elements.hashCode(); 35 | } 36 | 37 | @Override 38 | public String toString() { 39 | return "StringInterpolation{" + 40 | "elements=" + elements + 41 | 42 | '}'; 43 | } 44 | 45 | @Override 46 | public TypeUsage calcType() { 47 | return ReferenceTypeUsage.STRING(symbolResolver()); 48 | } 49 | 50 | /** 51 | * Note that also the StringLiterals are treated as the interpolated values (both are Expressions). 52 | * @param interpolatedValue 53 | */ 54 | public void add(Expression interpolatedValue) { 55 | elements.add(interpolatedValue); 56 | interpolatedValue.setParent(this); 57 | } 58 | 59 | @Override 60 | public Iterable getChildren() { 61 | return ImmutableList.copyOf(elements); 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /turin-compiler/src/main/java/me/tomassetti/turin/parser/ast/expressions/ThisExpression.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.turin.parser.ast.expressions; 2 | 3 | import me.tomassetti.turin.definitions.TypeDefinition; 4 | import me.tomassetti.turin.resolvers.SymbolResolver; 5 | import me.tomassetti.turin.parser.ast.Node; 6 | import me.tomassetti.turin.parser.ast.TurinTypeDefinition; 7 | import me.tomassetti.turin.typesystem.ReferenceTypeUsage; 8 | 9 | import java.util.Collections; 10 | 11 | public class ThisExpression extends Expression { 12 | 13 | public ThisExpression() { 14 | 15 | } 16 | 17 | @Override 18 | public String toString() { 19 | return "ThisExpression{}"; 20 | } 21 | 22 | @Override 23 | public Iterable getChildren() { 24 | return Collections.emptyList(); 25 | } 26 | 27 | @Override 28 | public ReferenceTypeUsage calcType() { 29 | TurinTypeDefinition turinTypeDefinition = getParentOfType(TurinTypeDefinition.class); 30 | return new ReferenceTypeUsage(turinTypeDefinition); 31 | } 32 | 33 | @Override 34 | public boolean canFieldBeAssigned(String field, SymbolResolver resolver) { 35 | TypeDefinition typeDefinition = calcType().getTypeDefinition(); 36 | return typeDefinition.canFieldBeAssigned(field); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /turin-compiler/src/main/java/me/tomassetti/turin/parser/ast/expressions/literals/BooleanLiteral.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.turin.parser.ast.expressions.literals; 2 | 3 | import me.tomassetti.turin.parser.ast.Node; 4 | import me.tomassetti.turin.parser.ast.expressions.Expression; 5 | import me.tomassetti.turin.typesystem.PrimitiveTypeUsage; 6 | import me.tomassetti.turin.typesystem.TypeUsage; 7 | 8 | import java.util.Collections; 9 | 10 | public class BooleanLiteral extends Expression { 11 | 12 | private boolean value; 13 | 14 | public BooleanLiteral(boolean value) { 15 | this.value = value; 16 | } 17 | 18 | @Override 19 | public TypeUsage calcType() { 20 | return PrimitiveTypeUsage.BOOLEAN; 21 | } 22 | 23 | @Override 24 | public Iterable getChildren() { 25 | return Collections.emptyList(); 26 | } 27 | 28 | public boolean getValue() { 29 | return value; 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /turin-compiler/src/main/java/me/tomassetti/turin/parser/ast/expressions/literals/ByteLiteral.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.turin.parser.ast.expressions.literals; 2 | 3 | import com.google.common.collect.ImmutableList; 4 | import me.tomassetti.turin.parser.ast.Node; 5 | import me.tomassetti.turin.parser.ast.expressions.Expression; 6 | import me.tomassetti.turin.typesystem.PrimitiveTypeUsage; 7 | import me.tomassetti.turin.typesystem.TypeUsage; 8 | 9 | public class ByteLiteral extends Expression { 10 | 11 | private byte value; 12 | 13 | public ByteLiteral(byte value) { 14 | this.value = value; 15 | } 16 | 17 | @Override 18 | public String toString() { 19 | return "ByteLiteral{" + 20 | "value=" + value + 21 | '}'; 22 | } 23 | 24 | @Override 25 | public boolean equals(Object o) { 26 | if (this == o) return true; 27 | if (o == null || getClass() != o.getClass()) return false; 28 | 29 | ByteLiteral that = (ByteLiteral) o; 30 | 31 | if (value != that.value) return false; 32 | 33 | return true; 34 | } 35 | 36 | @Override 37 | public int hashCode() { 38 | return value; 39 | } 40 | 41 | @Override 42 | public Iterable getChildren() { 43 | return ImmutableList.of(); 44 | } 45 | 46 | @Override 47 | public TypeUsage calcType() { 48 | return PrimitiveTypeUsage.BYTE; 49 | } 50 | 51 | public byte getValue() { 52 | return value; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /turin-compiler/src/main/java/me/tomassetti/turin/parser/ast/expressions/literals/DoubleLiteral.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.turin.parser.ast.expressions.literals; 2 | 3 | import com.google.common.collect.ImmutableList; 4 | import me.tomassetti.turin.parser.ast.Node; 5 | import me.tomassetti.turin.parser.ast.expressions.Expression; 6 | import me.tomassetti.turin.typesystem.PrimitiveTypeUsage; 7 | import me.tomassetti.turin.typesystem.TypeUsage; 8 | 9 | public class DoubleLiteral extends Expression { 10 | 11 | private double value; 12 | 13 | public DoubleLiteral(double value) { 14 | this.value = value; 15 | } 16 | 17 | @Override 18 | public String toString() { 19 | return "DoubleLiteral{" + 20 | "value=" + value + 21 | '}'; 22 | } 23 | 24 | @Override 25 | public boolean equals(Object o) { 26 | if (this == o) return true; 27 | if (o == null || getClass() != o.getClass()) return false; 28 | 29 | DoubleLiteral that = (DoubleLiteral) o; 30 | 31 | if (value != that.value) return false; 32 | 33 | return true; 34 | } 35 | 36 | @Override 37 | public int hashCode() { 38 | return Double.hashCode(value); 39 | } 40 | 41 | @Override 42 | public Iterable getChildren() { 43 | return ImmutableList.of(); 44 | } 45 | 46 | @Override 47 | public TypeUsage calcType() { 48 | return PrimitiveTypeUsage.DOUBLE; 49 | } 50 | 51 | public double getValue() { 52 | return value; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /turin-compiler/src/main/java/me/tomassetti/turin/parser/ast/expressions/literals/FloatLiteral.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.turin.parser.ast.expressions.literals; 2 | 3 | import me.tomassetti.turin.parser.ast.Node; 4 | import me.tomassetti.turin.parser.ast.expressions.Expression; 5 | import me.tomassetti.turin.typesystem.PrimitiveTypeUsage; 6 | import me.tomassetti.turin.typesystem.TypeUsage; 7 | 8 | import java.util.Collections; 9 | 10 | public class FloatLiteral extends Expression { 11 | 12 | private float value; 13 | 14 | public float getValue() { 15 | return value; 16 | } 17 | 18 | @Override 19 | public String toString() { 20 | return "FloatLiteral{" + 21 | "value=" + value + 22 | '}'; 23 | } 24 | 25 | @Override 26 | public boolean equals(Object o) { 27 | if (this == o) return true; 28 | if (!(o instanceof FloatLiteral)) return false; 29 | 30 | FloatLiteral that = (FloatLiteral) o; 31 | 32 | if (Float.compare(that.value, value) != 0) return false; 33 | 34 | return true; 35 | } 36 | 37 | @Override 38 | public int hashCode() { 39 | return (value != +0.0f ? Float.floatToIntBits(value) : 0); 40 | } 41 | 42 | public FloatLiteral(float value) { 43 | this.value = value; 44 | } 45 | 46 | @Override 47 | public TypeUsage calcType() { 48 | return PrimitiveTypeUsage.FLOAT; 49 | } 50 | 51 | @Override 52 | public Iterable getChildren() { 53 | return Collections.emptyList(); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /turin-compiler/src/main/java/me/tomassetti/turin/parser/ast/expressions/literals/IntLiteral.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.turin.parser.ast.expressions.literals; 2 | 3 | import com.google.common.collect.ImmutableList; 4 | import me.tomassetti.turin.parser.ast.Node; 5 | import me.tomassetti.turin.parser.ast.expressions.Expression; 6 | import me.tomassetti.turin.typesystem.PrimitiveTypeUsage; 7 | import me.tomassetti.turin.typesystem.TypeUsage; 8 | 9 | public class IntLiteral extends Expression { 10 | 11 | private int value; 12 | 13 | public IntLiteral(int value) { 14 | this.value = value; 15 | } 16 | 17 | @Override 18 | public String toString() { 19 | return "IntLiteral{" + 20 | "value=" + value + 21 | '}'; 22 | } 23 | 24 | @Override 25 | public boolean equals(Object o) { 26 | if (this == o) return true; 27 | if (o == null || getClass() != o.getClass()) return false; 28 | 29 | IntLiteral that = (IntLiteral) o; 30 | 31 | if (value != that.value) return false; 32 | 33 | return true; 34 | } 35 | 36 | @Override 37 | public int hashCode() { 38 | return value; 39 | } 40 | 41 | @Override 42 | public Iterable getChildren() { 43 | return ImmutableList.of(); 44 | } 45 | 46 | @Override 47 | public TypeUsage calcType() { 48 | return PrimitiveTypeUsage.INT; 49 | } 50 | 51 | public int getValue() { 52 | return value; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /turin-compiler/src/main/java/me/tomassetti/turin/parser/ast/expressions/literals/LongLiteral.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.turin.parser.ast.expressions.literals; 2 | 3 | import com.google.common.collect.ImmutableList; 4 | import me.tomassetti.turin.parser.ast.Node; 5 | import me.tomassetti.turin.parser.ast.expressions.Expression; 6 | import me.tomassetti.turin.typesystem.PrimitiveTypeUsage; 7 | import me.tomassetti.turin.typesystem.TypeUsage; 8 | 9 | public class LongLiteral extends Expression { 10 | 11 | private long value; 12 | 13 | public LongLiteral(long value) { 14 | this.value = value; 15 | } 16 | 17 | @Override 18 | public String toString() { 19 | return "LongLiteral{" + 20 | "value=" + value + 21 | '}'; 22 | } 23 | 24 | @Override 25 | public boolean equals(Object o) { 26 | if (this == o) return true; 27 | if (o == null || getClass() != o.getClass()) return false; 28 | 29 | LongLiteral that = (LongLiteral) o; 30 | 31 | if (value != that.value) return false; 32 | 33 | return true; 34 | } 35 | 36 | @Override 37 | public int hashCode() { 38 | return Long.hashCode(value); 39 | } 40 | 41 | @Override 42 | public Iterable getChildren() { 43 | return ImmutableList.of(); 44 | } 45 | 46 | @Override 47 | public TypeUsage calcType() { 48 | return PrimitiveTypeUsage.LONG; 49 | } 50 | 51 | public long getValue() { 52 | return value; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /turin-compiler/src/main/java/me/tomassetti/turin/parser/ast/expressions/literals/ShortLiteral.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.turin.parser.ast.expressions.literals; 2 | 3 | import com.google.common.collect.ImmutableList; 4 | import me.tomassetti.turin.parser.ast.Node; 5 | import me.tomassetti.turin.parser.ast.expressions.Expression; 6 | import me.tomassetti.turin.typesystem.PrimitiveTypeUsage; 7 | import me.tomassetti.turin.typesystem.TypeUsage; 8 | 9 | public class ShortLiteral extends Expression { 10 | 11 | private short value; 12 | 13 | public ShortLiteral(short value) { 14 | this.value = value; 15 | } 16 | 17 | @Override 18 | public String toString() { 19 | return "ShortLiteral{" + 20 | "value=" + value + 21 | '}'; 22 | } 23 | 24 | @Override 25 | public boolean equals(Object o) { 26 | if (this == o) return true; 27 | if (o == null || getClass() != o.getClass()) return false; 28 | 29 | ShortLiteral that = (ShortLiteral) o; 30 | 31 | if (value != that.value) return false; 32 | 33 | return true; 34 | } 35 | 36 | @Override 37 | public int hashCode() { 38 | return value; 39 | } 40 | 41 | @Override 42 | public Iterable getChildren() { 43 | return ImmutableList.of(); 44 | } 45 | 46 | @Override 47 | public TypeUsage calcType() { 48 | return PrimitiveTypeUsage.SHORT; 49 | } 50 | 51 | public short getValue() { 52 | return value; 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /turin-compiler/src/main/java/me/tomassetti/turin/parser/ast/expressions/literals/StringLiteral.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.turin.parser.ast.expressions.literals; 2 | 3 | import com.google.common.collect.ImmutableList; 4 | import me.tomassetti.turin.parser.ast.Node; 5 | import me.tomassetti.turin.parser.ast.expressions.Expression; 6 | import me.tomassetti.turin.typesystem.ReferenceTypeUsage; 7 | import me.tomassetti.turin.typesystem.TypeUsage; 8 | 9 | public class StringLiteral extends Expression { 10 | 11 | private String value; 12 | 13 | public StringLiteral(String value) { 14 | this.value = value; 15 | } 16 | 17 | @Override 18 | public String toString() { 19 | return "StringLiteral{" + 20 | "value='" + value + '\'' + 21 | '}'; 22 | } 23 | 24 | public String getValue() { 25 | return value; 26 | } 27 | 28 | @Override 29 | 30 | public boolean equals(Object o) { 31 | if (this == o) return true; 32 | if (o == null || getClass() != o.getClass()) return false; 33 | 34 | StringLiteral that = (StringLiteral) o; 35 | 36 | if (!value.equals(that.value)) return false; 37 | 38 | return true; 39 | } 40 | 41 | @Override 42 | public int hashCode() { 43 | return value.hashCode(); 44 | } 45 | 46 | @Override 47 | public Iterable getChildren() { 48 | return ImmutableList.of(); 49 | } 50 | 51 | @Override 52 | public TypeUsage calcType() { 53 | return ReferenceTypeUsage.STRING(symbolResolver()); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /turin-compiler/src/main/java/me/tomassetti/turin/parser/ast/expressions/relations/AccessEndpoint.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.turin.parser.ast.expressions.relations; 2 | 3 | import me.tomassetti.turin.parser.ast.Node; 4 | import me.tomassetti.turin.parser.ast.expressions.Expression; 5 | import me.tomassetti.turin.parser.ast.relations.RelationDefinition; 6 | import me.tomassetti.turin.parser.ast.relations.RelationFieldDefinition; 7 | import me.tomassetti.turin.symbols.Symbol; 8 | import me.tomassetti.turin.typesystem.TypeUsage; 9 | 10 | // This is a Symbol, not a Node 11 | public class AccessEndpoint extends Expression { 12 | 13 | private Symbol instance; 14 | private RelationFieldDefinition relationField; 15 | 16 | public Symbol getInstance() { 17 | return instance; 18 | } 19 | 20 | public RelationFieldDefinition getRelationField() { 21 | return relationField; 22 | } 23 | 24 | public AccessEndpoint(Symbol instance, RelationFieldDefinition relationField) { 25 | this.instance = instance; 26 | this.relationField = relationField; 27 | } 28 | 29 | @Override 30 | public Iterable getChildren() { 31 | throw new UnsupportedOperationException(); 32 | } 33 | 34 | @Override 35 | public TypeUsage calcType() { 36 | return relationField.calcType(); 37 | } 38 | 39 | public RelationDefinition getRelationDefinition() { 40 | return relationField.getRelationDefinition(); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /turin-compiler/src/main/java/me/tomassetti/turin/parser/ast/imports/AllPackageImportDeclaration.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.turin.parser.ast.imports; 2 | 3 | import com.google.common.collect.ImmutableList; 4 | import me.tomassetti.turin.compiler.errorhandling.ErrorCollector; 5 | import me.tomassetti.jvm.JvmNameUtils; 6 | import me.tomassetti.turin.definitions.TypeDefinition; 7 | import me.tomassetti.turin.resolvers.SymbolResolver; 8 | import me.tomassetti.turin.parser.ast.Node; 9 | import me.tomassetti.turin.parser.ast.QualifiedName; 10 | import me.tomassetti.turin.symbols.Symbol; 11 | 12 | import java.util.Optional; 13 | 14 | public class AllPackageImportDeclaration extends ImportDeclaration { 15 | 16 | private QualifiedName qualifiedName; 17 | 18 | public AllPackageImportDeclaration(QualifiedName qualifiedName) { 19 | this.qualifiedName = qualifiedName; 20 | } 21 | 22 | @Override 23 | protected boolean specificValidate(SymbolResolver resolver, ErrorCollector errorCollector) { 24 | if (!resolver.existPackage(qualifiedName.qualifiedName())) { 25 | errorCollector.recordSemanticError(getPosition(), "Import not resolved: " + qualifiedName.qualifiedName()); 26 | return false; 27 | } 28 | 29 | return super.specificValidate(resolver, errorCollector); 30 | } 31 | 32 | @Override 33 | public Optional findAmongImported(String name, SymbolResolver resolver) { 34 | // TODO correct the context passed 35 | if (JvmNameUtils.isSimpleName(name)) { 36 | Optional res = resolver.findTypeDefinitionIn(qualifiedName.qualifiedName() + "." + name, this, resolver); 37 | if (res.isPresent()) { 38 | return Optional.of(res.get()); 39 | } else { 40 | return Optional.empty(); 41 | } 42 | } else { 43 | return Optional.empty(); 44 | } 45 | } 46 | 47 | @Override 48 | public Iterable getChildren() { 49 | return ImmutableList.of(qualifiedName); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /turin-compiler/src/main/java/me/tomassetti/turin/parser/ast/imports/ImportDeclaration.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.turin.parser.ast.imports; 2 | 3 | import me.tomassetti.turin.resolvers.SymbolResolver; 4 | import me.tomassetti.turin.parser.ast.Node; 5 | import me.tomassetti.turin.symbols.Symbol; 6 | 7 | import java.util.Optional; 8 | 9 | public abstract class ImportDeclaration extends Node { 10 | 11 | public abstract Optional findAmongImported(String name, SymbolResolver resolver); 12 | } 13 | -------------------------------------------------------------------------------- /turin-compiler/src/main/java/me/tomassetti/turin/parser/ast/invokables/TurinTypeContructorDefinitionNode.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.turin.parser.ast.invokables; 2 | 3 | import com.google.common.collect.ImmutableList; 4 | import me.tomassetti.turin.parser.ast.FormalParameterNode; 5 | import me.tomassetti.turin.parser.ast.Node; 6 | import me.tomassetti.turin.parser.ast.statements.BlockStatement; 7 | import me.tomassetti.turin.parser.ast.statements.Statement; 8 | import me.tomassetti.turin.parser.ast.typeusage.VoidTypeUsageNode; 9 | 10 | import java.util.List; 11 | 12 | /** 13 | * Definition of a method in a Turin Type. 14 | */ 15 | public class TurinTypeContructorDefinitionNode extends InvokableDefinitionNode { 16 | 17 | public Statement getBody() { 18 | return body; 19 | } 20 | 21 | public TurinTypeContructorDefinitionNode(List parameters, BlockStatement body) { 22 | super(parameters, body, "", new VoidTypeUsageNode()); 23 | } 24 | 25 | @Override 26 | public Iterable getChildren() { 27 | return ImmutableList.builder() 28 | .addAll(parameters) 29 | .add(body) 30 | .build(); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /turin-compiler/src/main/java/me/tomassetti/turin/parser/ast/invokables/TurinTypeMethodDefinitionNode.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.turin.parser.ast.invokables; 2 | 3 | import me.tomassetti.turin.parser.ast.FormalParameterNode; 4 | import me.tomassetti.turin.parser.ast.statements.Statement; 5 | import me.tomassetti.turin.parser.ast.typeusage.TypeUsageNode; 6 | 7 | import java.util.List; 8 | 9 | /** 10 | * Definition of a method in a Turin Type. 11 | */ 12 | public class TurinTypeMethodDefinitionNode extends InvokableDefinitionNode { 13 | 14 | public TurinTypeMethodDefinitionNode(String name, TypeUsageNode returnType, List parameters, Statement body) { 15 | super(parameters, body, name, returnType); 16 | this.returnType.setParent(this); 17 | this.parameters.forEach((p) -> p.setParent(TurinTypeMethodDefinitionNode.this) ); 18 | this.body.setParent(this); 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /turin-compiler/src/main/java/me/tomassetti/turin/parser/ast/properties/PropertyConstraint.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.turin.parser.ast.properties; 2 | 3 | import com.google.common.collect.ImmutableList; 4 | import me.tomassetti.turin.compiler.errorhandling.ErrorCollector; 5 | import me.tomassetti.turin.resolvers.SymbolResolver; 6 | import me.tomassetti.turin.parser.ast.Node; 7 | import me.tomassetti.turin.parser.ast.expressions.Expression; 8 | import me.tomassetti.turin.typesystem.TypeUsage; 9 | 10 | public class PropertyConstraint extends Node { 11 | private Expression condition; 12 | private Expression message; 13 | 14 | public PropertyConstraint(Expression condition, Expression message) { 15 | this.condition = condition; 16 | this.condition.setParent(this); 17 | this.message = message; 18 | this.message.setParent(this); 19 | } 20 | 21 | public Expression getCondition() { 22 | return condition; 23 | } 24 | 25 | public Expression getMessage() { 26 | return message; 27 | } 28 | 29 | @Override 30 | public Iterable getChildren() { 31 | return ImmutableList.of(condition, message); 32 | } 33 | 34 | @Override 35 | protected boolean specificValidate(SymbolResolver resolver, ErrorCollector errorCollector) { 36 | TypeUsage conditionType = condition.calcType(); 37 | if (!conditionType.isPrimitive() || !conditionType.asPrimitiveTypeUsage().isBoolean()) { 38 | errorCollector.recordSemanticError(condition.getPosition(), "A property constraint condition must have boolean type, instead it has type " + conditionType.describe()); 39 | return false; 40 | } 41 | TypeUsage messageType = message.calcType(); 42 | if (!messageType.isReference() || 43 | !messageType.asReferenceTypeUsage().getQualifiedName().equals(String.class.getCanonicalName())) { 44 | errorCollector.recordSemanticError(condition.getPosition(), "A property constraint message must have String type, instead it has type " + messageType.describe()); 45 | return false; 46 | } 47 | return super.specificValidate(resolver, errorCollector); 48 | } 49 | 50 | 51 | } 52 | -------------------------------------------------------------------------------- /turin-compiler/src/main/java/me/tomassetti/turin/parser/ast/properties/PropertyReference.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.turin.parser.ast.properties; 2 | 3 | import com.google.common.collect.ImmutableList; 4 | import me.tomassetti.turin.parser.analysis.exceptions.UnsolvedSymbolException; 5 | import me.tomassetti.turin.resolvers.SymbolResolver; 6 | import me.tomassetti.turin.parser.ast.Node; 7 | import me.tomassetti.turin.typesystem.TypeUsage; 8 | 9 | import java.util.Optional; 10 | 11 | public class PropertyReference extends Node { 12 | public String getName() { 13 | return name; 14 | } 15 | 16 | private String name; 17 | 18 | public PropertyReference(String name) { 19 | this.name = name; 20 | } 21 | 22 | @Override 23 | public Iterable getChildren() { 24 | return ImmutableList.of(); 25 | } 26 | 27 | public TypeUsage getType(SymbolResolver resolver) { 28 | Optional propertyDefinition = resolver.findDefinition(this); 29 | if (propertyDefinition.isPresent()) { 30 | return propertyDefinition.get().getType(); 31 | } else { 32 | throw new UnsolvedSymbolException(this); 33 | } 34 | } 35 | 36 | @Override 37 | public String toString() { 38 | return "PropertyReference{" + 39 | "name='" + name + '\'' + 40 | '}'; 41 | } 42 | 43 | @Override 44 | public boolean equals(Object o) { 45 | if (this == o) return true; 46 | if (o == null || getClass() != o.getClass()) return false; 47 | 48 | PropertyReference that = (PropertyReference) o; 49 | 50 | if (!name.equals(that.name)) return false; 51 | 52 | return true; 53 | } 54 | 55 | @Override 56 | public int hashCode() { 57 | return name.hashCode(); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /turin-compiler/src/main/java/me/tomassetti/turin/parser/ast/statements/BlockStatement.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.turin.parser.ast.statements; 2 | 3 | import com.google.common.collect.ImmutableList; 4 | import me.tomassetti.turin.parser.ast.Node; 5 | 6 | import java.util.List; 7 | 8 | public class BlockStatement extends Statement { 9 | 10 | private List statements; 11 | 12 | @Override 13 | public boolean equals(Object o) { 14 | if (this == o) return true; 15 | if (o == null || getClass() != o.getClass()) return false; 16 | 17 | BlockStatement that = (BlockStatement) o; 18 | 19 | if (!statements.equals(that.statements)) return false; 20 | 21 | return true; 22 | } 23 | 24 | public List getStatements() { 25 | return statements; 26 | } 27 | 28 | @Override 29 | public String toString() { 30 | return "BlockStatement{" + 31 | "statements=" + statements + 32 | '}'; 33 | } 34 | 35 | @Override 36 | public int hashCode() { 37 | return statements.hashCode(); 38 | } 39 | 40 | public BlockStatement(List statements) { 41 | this.statements = statements; 42 | this.statements.forEach((s) -> s.setParent(BlockStatement.this)); 43 | } 44 | 45 | @Override 46 | public Iterable getChildren() { 47 | return ImmutableList.copyOf(statements); 48 | } 49 | 50 | public List findPreeceding(Statement statement) { 51 | for (int i=0;i getChildren() { 46 | return ImmutableList.of(exceptionType, body); 47 | } 48 | 49 | @Override 50 | public Optional findSymbol(String name, SymbolResolver resolver) { 51 | if (name.equals(variableName)) { 52 | return Optional.of(this); 53 | } 54 | return super.findSymbol(name, resolver); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /turin-compiler/src/main/java/me/tomassetti/turin/parser/ast/statements/ContextAssignment.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.turin.parser.ast.statements; 2 | 3 | import com.google.common.collect.ImmutableList; 4 | import me.tomassetti.turin.compiler.errorhandling.ErrorCollector; 5 | import me.tomassetti.turin.definitions.ContextDefinition; 6 | import me.tomassetti.turin.parser.ast.Node; 7 | import me.tomassetti.turin.parser.ast.expressions.Expression; 8 | import me.tomassetti.turin.resolvers.SymbolResolver; 9 | import me.tomassetti.turin.symbols.Symbol; 10 | 11 | import java.util.Collections; 12 | import java.util.Optional; 13 | 14 | public class ContextAssignment extends Node { 15 | 16 | private String contextName; 17 | private Expression contextValue; 18 | private Optional contextSymbol; 19 | 20 | public ContextAssignment(String contextName, Expression contextValue) { 21 | this.contextName = contextName; 22 | this.contextValue = contextValue; 23 | this.contextValue.setParent(this); 24 | } 25 | 26 | public Optional contextSymbol() { 27 | if (contextSymbol == null) { 28 | contextSymbol = symbolResolver().findContextSymbol(contextName, this); 29 | } 30 | return contextSymbol; 31 | } 32 | 33 | @Override 34 | protected boolean specificValidate(SymbolResolver resolver, ErrorCollector errorCollector) { 35 | Optional contextSymbolOptional = resolver.findContextSymbol(contextName, this); 36 | if (!contextSymbolOptional.isPresent()) { 37 | errorCollector.recordSemanticError(getPosition(), "Context "+ contextName + " cannot be resolved"); 38 | return false; 39 | } 40 | return super.specificValidate(resolver, errorCollector); 41 | } 42 | 43 | public Expression getContextValue() { 44 | return contextValue; 45 | } 46 | 47 | @Override 48 | public Iterable getChildren() { 49 | return ImmutableList.of(contextValue); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /turin-compiler/src/main/java/me/tomassetti/turin/parser/ast/statements/ContextScope.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.turin.parser.ast.statements; 2 | 3 | import com.google.common.collect.ImmutableList; 4 | import me.tomassetti.turin.parser.ast.Node; 5 | 6 | import java.util.List; 7 | 8 | public class ContextScope extends Statement { 9 | 10 | private List assignments; 11 | private List statements; 12 | 13 | public ContextScope(List assignments, List statements) { 14 | this.assignments = assignments; 15 | this.assignments.forEach((a)->a.setParent(ContextScope.this)); 16 | this.statements = statements; 17 | this.statements.forEach((s)->s.setParent(ContextScope.this)); 18 | } 19 | 20 | public List getStatements() { 21 | return statements; 22 | } 23 | 24 | public List getAssignments() { 25 | return assignments; 26 | } 27 | 28 | @Override 29 | public Iterable getChildren() { 30 | return ImmutableList.builder() 31 | .addAll(assignments) 32 | .addAll(statements) 33 | .build(); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /turin-compiler/src/main/java/me/tomassetti/turin/parser/ast/statements/ElifClause.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.turin.parser.ast.statements; 2 | 3 | import com.google.common.collect.ImmutableList; 4 | import me.tomassetti.turin.parser.ast.Node; 5 | import me.tomassetti.turin.parser.ast.expressions.Expression; 6 | 7 | public class ElifClause extends Node { 8 | 9 | private Expression condition; 10 | private BlockStatement body; 11 | 12 | public ElifClause(Expression condition, BlockStatement body) { 13 | this.condition = condition; 14 | this.condition.setParent(this); 15 | this.body = body; 16 | this.body.setParent(this); 17 | } 18 | 19 | public Expression getCondition() { 20 | return condition; 21 | } 22 | 23 | public BlockStatement getBody() { 24 | return body; 25 | } 26 | 27 | @Override 28 | public Iterable getChildren() { 29 | return ImmutableList.of(condition, body); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /turin-compiler/src/main/java/me/tomassetti/turin/parser/ast/statements/ExpressionStatement.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.turin.parser.ast.statements; 2 | 3 | import com.google.common.collect.ImmutableList; 4 | import me.tomassetti.turin.parser.ast.Node; 5 | import me.tomassetti.turin.parser.ast.expressions.Expression; 6 | 7 | public class ExpressionStatement extends Statement { 8 | private Expression expression; 9 | 10 | public ExpressionStatement(Expression expression) { 11 | this.expression = expression; 12 | this.expression.setParent(this); 13 | } 14 | 15 | @Override 16 | public String toString() { 17 | return "ExpressionStatement{" + 18 | "expression=" + expression + 19 | '}'; 20 | } 21 | 22 | @Override 23 | public boolean equals(Object o) { 24 | if (this == o) return true; 25 | if (o == null || getClass() != o.getClass()) return false; 26 | 27 | ExpressionStatement that = (ExpressionStatement) o; 28 | 29 | if (!expression.equals(that.expression)) return false; 30 | 31 | return true; 32 | } 33 | 34 | @Override 35 | public int hashCode() { 36 | return expression.hashCode(); 37 | } 38 | 39 | @Override 40 | 41 | public Iterable getChildren() { 42 | return ImmutableList.of(expression); 43 | } 44 | 45 | public Expression getExpression() { 46 | return expression; 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /turin-compiler/src/main/java/me/tomassetti/turin/parser/ast/statements/ReturnStatement.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.turin.parser.ast.statements; 2 | 3 | import com.google.common.collect.ImmutableList; 4 | import me.tomassetti.turin.parser.ast.Node; 5 | import me.tomassetti.turin.parser.ast.expressions.Expression; 6 | 7 | public class ReturnStatement extends Statement { 8 | private Expression value; 9 | 10 | public ReturnStatement(Expression value) { 11 | this.value = value; 12 | this.value.setParent(this); 13 | } 14 | 15 | public ReturnStatement() { 16 | } 17 | 18 | public Expression getValue() { 19 | return value; 20 | } 21 | 22 | @Override 23 | public Iterable getChildren() { 24 | return ImmutableList.of(value); 25 | } 26 | 27 | public boolean hasValue() { 28 | return value != null; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /turin-compiler/src/main/java/me/tomassetti/turin/parser/ast/statements/Statement.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.turin.parser.ast.statements; 2 | 3 | import me.tomassetti.turin.parser.ast.Node; 4 | 5 | import java.util.List; 6 | 7 | public abstract class Statement extends Node { 8 | } 9 | -------------------------------------------------------------------------------- /turin-compiler/src/main/java/me/tomassetti/turin/parser/ast/statements/SuperInvokation.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.turin.parser.ast.statements; 2 | 3 | import com.google.common.collect.ImmutableList; 4 | import me.tomassetti.jvm.JvmConstructorDefinition; 5 | import me.tomassetti.turin.resolvers.SymbolResolver; 6 | import me.tomassetti.turin.parser.ast.Node; 7 | import me.tomassetti.turin.parser.ast.TurinTypeDefinition; 8 | import me.tomassetti.turin.parser.ast.expressions.ActualParam; 9 | import me.tomassetti.turin.parser.ast.expressions.InvokableExpr; 10 | import me.tomassetti.turin.parser.ast.typeusage.TypeUsageNode; 11 | import me.tomassetti.turin.symbols.FormalParameter; 12 | 13 | import java.util.List; 14 | import java.util.Optional; 15 | 16 | public class SuperInvokation extends InvokableExpr { 17 | 18 | @Override 19 | public String toString() { 20 | return "SuperInvokation{" + 21 | "params=" + actualParams + 22 | '}'; 23 | } 24 | 25 | private TurinTypeDefinition getTurinTypeDefinition() { 26 | return getParentOfType(TurinTypeDefinition.class); 27 | } 28 | 29 | public SuperInvokation(List params) { 30 | super(params); 31 | } 32 | 33 | @Override 34 | public boolean isOnOverloaded(SymbolResolver resolver) { 35 | return getTurinTypeDefinition().hasManyConstructors(); 36 | } 37 | 38 | @Override 39 | protected List formalParameters(SymbolResolver resolver) { 40 | return getTurinTypeDefinition().getSuperclass().getConstructorParams(actualParams); 41 | } 42 | 43 | @Override 44 | public Iterable getChildren() { 45 | return ImmutableList.copyOf(actualParams); 46 | } 47 | 48 | 49 | @Override 50 | public TypeUsageNode calcType() { 51 | throw new UnsupportedOperationException(); 52 | } 53 | 54 | public Optional findJvmDefinition(SymbolResolver resolver) { 55 | return getTurinTypeDefinition().getSuperclass().findConstructorDefinition(actualParams); 56 | } 57 | } 58 | 59 | -------------------------------------------------------------------------------- /turin-compiler/src/main/java/me/tomassetti/turin/parser/ast/statements/TryCatchStatement.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.turin.parser.ast.statements; 2 | 3 | import com.google.common.collect.ImmutableList; 4 | import me.tomassetti.turin.parser.ast.Node; 5 | 6 | import java.util.List; 7 | 8 | public class TryCatchStatement extends Statement { 9 | 10 | private BlockStatement body; 11 | private List catchClauses; 12 | 13 | public BlockStatement getBody() { 14 | return body; 15 | } 16 | 17 | public List getCatchClauses() { 18 | return catchClauses; 19 | } 20 | 21 | public TryCatchStatement(BlockStatement body, List catchClauses) { 22 | this.body = body; 23 | this.body.setParent(this); 24 | this.catchClauses = catchClauses; 25 | this.catchClauses.forEach((cc)->cc.setParent(TryCatchStatement.this)); 26 | } 27 | 28 | @Override 29 | public Iterable getChildren() { 30 | return ImmutableList.builder().add(body).addAll(catchClauses).build(); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /turin-compiler/src/main/java/me/tomassetti/turin/parser/ast/typeusage/ArrayTypeUsageNode.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.turin.parser.ast.typeusage; 2 | 3 | import com.google.common.collect.ImmutableList; 4 | import me.tomassetti.turin.parser.ast.Node; 5 | import me.tomassetti.turin.typesystem.ArrayTypeUsage; 6 | 7 | public class ArrayTypeUsageNode extends TypeUsageWrapperNode { 8 | 9 | private TypeUsageNode componentTypeNode; 10 | 11 | public ArrayTypeUsageNode(TypeUsageNode componentType) { 12 | super(new ArrayTypeUsage(componentType)); 13 | this.componentTypeNode = componentType; 14 | } 15 | 16 | @Override 17 | public String toString() { 18 | return "ArrayTypeUsage{" + 19 | "componentTypeNode=" + componentTypeNode + 20 | '}'; 21 | } 22 | 23 | @Override 24 | public TypeUsageNode copy() { 25 | ArrayTypeUsageNode copy = new ArrayTypeUsageNode(this.componentTypeNode); 26 | copy.parent = this.parent; 27 | return copy; 28 | } 29 | 30 | @Override 31 | public boolean equals(Object o) { 32 | if (this == o) return true; 33 | if (o == null || getClass() != o.getClass()) return false; 34 | 35 | ArrayTypeUsageNode that = (ArrayTypeUsageNode) o; 36 | 37 | if (!componentTypeNode.equals(that.componentTypeNode)) return false; 38 | 39 | return true; 40 | } 41 | 42 | @Override 43 | public int hashCode() { 44 | return componentTypeNode.hashCode(); 45 | } 46 | 47 | @Override 48 | public Iterable getChildren() { 49 | return ImmutableList.of(componentTypeNode); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /turin-compiler/src/main/java/me/tomassetti/turin/parser/ast/typeusage/BasicTypeUsageNode.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.turin.parser.ast.typeusage; 2 | 3 | import me.tomassetti.turin.parser.ast.Node; 4 | import me.tomassetti.turin.typesystem.UnsignedPrimitiveTypeUsage; 5 | 6 | import java.util.Collections; 7 | 8 | /** 9 | * NOTE: Being a Node we could need to have separate instances for each occurrence, so that each one can have a proper 10 | * parent. 11 | */ 12 | public class BasicTypeUsageNode extends TypeUsageWrapperNode { 13 | 14 | public BasicTypeUsageNode(String name) { 15 | super(UnsignedPrimitiveTypeUsage.getByName(name)); 16 | } 17 | 18 | @Override 19 | public TypeUsageNode copy() { 20 | return this; 21 | } 22 | 23 | @Override 24 | public Iterable getChildren() { 25 | return Collections.emptyList(); 26 | } 27 | 28 | @Override 29 | public String toString() { 30 | return "BasicTypeUsageNode{" + typeUsage + "}"; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /turin-compiler/src/main/java/me/tomassetti/turin/parser/ast/typeusage/TypeVariableTypeNode.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.turin.parser.ast.typeusage; 2 | 3 | import me.tomassetti.turin.parser.ast.Node; 4 | import me.tomassetti.turin.typesystem.ConcreteTypeVariableUsage; 5 | import me.tomassetti.turin.typesystem.TypeVariableUsage; 6 | 7 | import java.util.List; 8 | 9 | public class TypeVariableTypeNode extends TypeUsageWrapperNode { 10 | 11 | @Override 12 | public TypeUsageNode copy() { 13 | throw new UnsupportedOperationException(); 14 | } 15 | 16 | private String name; 17 | private List bounds; 18 | private TypeVariableUsage.GenericDeclaration genericDeclaration; 19 | 20 | public TypeVariableTypeNode(TypeVariableUsage.GenericDeclaration genericDeclaration, String name, List bounds) { 21 | super(new ConcreteTypeVariableUsage(genericDeclaration, name, bounds)); 22 | this.name = name; 23 | this.genericDeclaration = genericDeclaration; 24 | this.bounds = bounds; 25 | } 26 | 27 | @Override 28 | public Iterable getChildren() { 29 | throw new UnsupportedOperationException(); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /turin-compiler/src/main/java/me/tomassetti/turin/parser/ast/typeusage/VoidTypeUsageNode.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.turin.parser.ast.typeusage; 2 | 3 | import me.tomassetti.turin.parser.ast.Node; 4 | import me.tomassetti.turin.typesystem.TypeUsage; 5 | import me.tomassetti.turin.typesystem.VoidTypeUsage; 6 | 7 | import java.util.Collections; 8 | import java.util.Map; 9 | 10 | public class VoidTypeUsageNode extends TypeUsageWrapperNode { 11 | 12 | public VoidTypeUsageNode() { 13 | super(new VoidTypeUsage()); 14 | } 15 | 16 | @Override 17 | public TypeUsageNode copy() { 18 | return this; 19 | } 20 | 21 | @Override 22 | public Iterable getChildren() { 23 | return Collections.emptyList(); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /turin-compiler/src/main/java/me/tomassetti/turin/parser/ast/virtual/ArrayLength.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.turin.parser.ast.virtual; 2 | 3 | import me.tomassetti.turin.symbols.Symbol; 4 | import me.tomassetti.turin.typesystem.PrimitiveTypeUsage; 5 | import me.tomassetti.turin.typesystem.TypeUsage; 6 | 7 | public class ArrayLength implements Symbol { 8 | 9 | private Symbol array; 10 | 11 | public ArrayLength(Symbol array) { 12 | // non setting the parent of array on purpose 13 | this.array = array; 14 | } 15 | 16 | @Override 17 | public TypeUsage calcType() { 18 | return PrimitiveTypeUsage.INT; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /turin-compiler/src/main/java/me/tomassetti/turin/resolvers/ResolverProvider.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.turin.resolvers; 2 | 3 | import me.tomassetti.turin.parser.ast.Node; 4 | 5 | import java.util.Optional; 6 | 7 | /** 8 | * Created by federico on 16/10/15. 9 | */ 10 | public interface ResolverProvider { 11 | Optional findResolver(Node node); 12 | 13 | SymbolResolver requireResolver(Node node); 14 | } 15 | -------------------------------------------------------------------------------- /turin-compiler/src/main/java/me/tomassetti/turin/resolvers/ResolverRegistry.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.turin.resolvers; 2 | 3 | import me.tomassetti.turin.parser.ast.Node; 4 | 5 | import java.util.IdentityHashMap; 6 | import java.util.Map; 7 | import java.util.Optional; 8 | 9 | public enum ResolverRegistry implements ResolverProvider { 10 | 11 | INSTANCE; 12 | 13 | public void record(Node node, SymbolResolver resolver) { 14 | if (!node.isRoot()) { 15 | throw new IllegalArgumentException(); 16 | } 17 | resolvers.put(node, resolver); 18 | } 19 | 20 | @Override 21 | public Optional findResolver(Node node) { 22 | Node root = node.getRoot(); 23 | if (resolvers.containsKey(root)) { 24 | return Optional.of(resolvers.get(root)); 25 | } else { 26 | return Optional.empty(); 27 | } 28 | } 29 | 30 | @Override 31 | public SymbolResolver requireResolver(Node node) { 32 | Optional or = findResolver(node); 33 | if (or.isPresent()) { 34 | return or.get(); 35 | } else { 36 | throw new IllegalStateException(node.toString()); 37 | } 38 | } 39 | 40 | private Map resolvers = new IdentityHashMap<>(); 41 | 42 | } 43 | -------------------------------------------------------------------------------- /turin-compiler/src/main/java/me/tomassetti/turin/resolvers/TypeResolver.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.turin.resolvers; 2 | 3 | import me.tomassetti.turin.definitions.TypeDefinition; 4 | import me.tomassetti.turin.parser.ast.invokables.FunctionDefinitionNode; 5 | 6 | import java.util.Optional; 7 | 8 | public interface TypeResolver { 9 | 10 | public TypeResolver root(); 11 | public void setRoot(TypeResolver root); 12 | 13 | public Optional resolveAbsoluteTypeName(String typeName); 14 | public Optional resolveAbsoluteFunctionName(String typeName); 15 | 16 | boolean existPackage(String packageName); 17 | 18 | SymbolResolver symbolResolver(); 19 | void setSymbolResolver(SymbolResolver symbolResolver); 20 | } 21 | -------------------------------------------------------------------------------- /turin-compiler/src/main/java/me/tomassetti/turin/resolvers/compiled/ClassPoolFactory.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.turin.resolvers.compiled; 2 | 3 | import javassist.ClassPath; 4 | import javassist.ClassPool; 5 | 6 | public enum ClassPoolFactory { 7 | 8 | INSTANCE; 9 | 10 | // true means use the system path 11 | private ClassPool classPool = new ClassPool(true); 12 | 13 | public void addJar(ClassPath classPath) { 14 | classPool.appendClassPath(classPath); 15 | } 16 | public void addClassesDir(ClassPath classPath) { 17 | classPool.appendClassPath(classPath); 18 | } 19 | 20 | public ClassPool getClassPool() { 21 | return classPool; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /turin-compiler/src/main/java/me/tomassetti/turin/resolvers/compiled/ClasspathElement.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.turin.resolvers.compiled; 2 | 3 | import javassist.CtClass; 4 | 5 | import java.io.IOException; 6 | import java.io.InputStream; 7 | import java.net.URL; 8 | 9 | interface ClasspathElement { 10 | CtClass toCtClass() throws IOException; 11 | InputStream toInputStream() throws IOException; 12 | public URL toURL(); 13 | } 14 | -------------------------------------------------------------------------------- /turin-compiler/src/main/java/me/tomassetti/turin/resolvers/compiled/DirClassesClasspathElement.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.turin.resolvers.compiled; 2 | 3 | import javassist.ClassPool; 4 | import javassist.CtClass; 5 | 6 | import java.io.File; 7 | import java.io.FileInputStream; 8 | import java.io.IOException; 9 | import java.io.InputStream; 10 | import java.net.MalformedURLException; 11 | import java.net.URL; 12 | 13 | class DirClassesClasspathElement implements ClasspathElement { 14 | private File file; 15 | private String path; 16 | 17 | public DirClassesClasspathElement(File file, String path) { 18 | this.file = file; 19 | this.path = path; 20 | } 21 | 22 | @Override 23 | public InputStream toInputStream() throws IOException { 24 | return new FileInputStream(file); 25 | } 26 | 27 | @Override 28 | public CtClass toCtClass() throws IOException { 29 | InputStream is = toInputStream(); 30 | ClassPool classPool = ClassPoolFactory.INSTANCE.getClassPool(); 31 | CtClass ctClass = classPool.makeClass(is); 32 | return ctClass; 33 | } 34 | 35 | @Override 36 | public URL toURL() { 37 | String urlContent = "file:"+file.getAbsolutePath(); 38 | try { 39 | return new URL(urlContent); 40 | } catch (MalformedURLException e) { 41 | throw new RuntimeException("URL was: " + urlContent, e); 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /turin-compiler/src/main/java/me/tomassetti/turin/resolvers/compiled/JarClasspathElement.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.turin.resolvers.compiled; 2 | 3 | import javassist.ClassPool; 4 | import javassist.CtClass; 5 | 6 | import java.io.IOException; 7 | import java.io.InputStream; 8 | import java.net.MalformedURLException; 9 | import java.net.URL; 10 | import java.util.jar.JarEntry; 11 | import java.util.jar.JarFile; 12 | 13 | class JarClasspathElement implements ClasspathElement { 14 | private JarTypeResolver jarTypeResolver; 15 | private JarFile jarFile; 16 | private JarEntry entry; 17 | private String path; 18 | 19 | public JarClasspathElement(JarTypeResolver jarTypeResolver, JarFile jarFile, JarEntry entry, String path) { 20 | this.jarTypeResolver = jarTypeResolver; 21 | this.jarFile = jarFile; 22 | this.entry = entry; 23 | this.path = path; 24 | } 25 | 26 | @Override 27 | public InputStream toInputStream() throws IOException { 28 | return jarFile.getInputStream(entry); 29 | } 30 | 31 | @Override 32 | public CtClass toCtClass() throws IOException { 33 | InputStream is = toInputStream(); 34 | ClassPool classPool = ClassPoolFactory.INSTANCE.getClassPool(); 35 | CtClass ctClass = classPool.makeClass(is); 36 | return ctClass; 37 | } 38 | 39 | @Override 40 | public URL toURL() { 41 | String urlContent = "jar:file:"+ jarTypeResolver.file.getAbsolutePath()+"!/"+entry.getName(); 42 | try { 43 | return new URL(urlContent); 44 | } catch (MalformedURLException e) { 45 | throw new RuntimeException("URL was: " + urlContent, e); 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /turin-compiler/src/main/java/me/tomassetti/turin/resolvers/compiled/LoadedFunctionDefinition.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.turin.resolvers.compiled; 2 | 3 | import com.google.common.collect.ImmutableList; 4 | import me.tomassetti.jvm.JvmNameUtils; 5 | import me.tomassetti.turin.parser.ast.FormalParameterNode; 6 | import me.tomassetti.turin.parser.ast.invokables.FunctionDefinitionNode; 7 | import me.tomassetti.turin.parser.ast.statements.BlockStatement; 8 | import me.tomassetti.turin.parser.ast.typeusage.TypeUsageNode; 9 | 10 | import java.util.List; 11 | 12 | // TODO it should not be a Node 13 | public class LoadedFunctionDefinition extends FunctionDefinitionNode { 14 | 15 | private String qualifiedName; 16 | 17 | public LoadedFunctionDefinition(String qualifiedName, TypeUsageNode returnType, List parameters) { 18 | super(JvmNameUtils.canonicalToSimple(qualifiedName), returnType, parameters, new BlockStatement(ImmutableList.of())); 19 | this.qualifiedName = qualifiedName; 20 | } 21 | 22 | protected String getGeneratedClassQualifiedName() { 23 | String packagePart = JvmNameUtils.getPackagePart(qualifiedName); 24 | String simpleName = JvmNameUtils.getSimplePart(qualifiedName); 25 | String qName = packagePart + "." + CLASS_PREFIX + simpleName; 26 | if (!JvmNameUtils.isValidQualifiedName(qName)) { 27 | throw new IllegalStateException(qName); 28 | } 29 | return qName; 30 | } 31 | 32 | @Override 33 | public String getQualifiedName() { 34 | return qualifiedName; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /turin-compiler/src/main/java/me/tomassetti/turin/resolvers/jdk/JdkTypeResolver.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.turin.resolvers.jdk; 2 | 3 | import me.tomassetti.jvm.JvmNameUtils; 4 | import me.tomassetti.turin.definitions.TypeDefinition; 5 | import me.tomassetti.turin.resolvers.SymbolResolver; 6 | import me.tomassetti.turin.resolvers.TypeResolver; 7 | import me.tomassetti.turin.parser.ast.invokables.FunctionDefinitionNode; 8 | 9 | import java.util.Optional; 10 | 11 | public class JdkTypeResolver implements TypeResolver { 12 | 13 | private static JdkTypeResolver INSTANCE = new JdkTypeResolver(); 14 | 15 | private JdkTypeResolver() { 16 | 17 | } 18 | 19 | protected SymbolResolver symbolResolver; 20 | 21 | public SymbolResolver symbolResolver() { 22 | if (this.root() == this) { 23 | return symbolResolver.getRoot(); 24 | } 25 | return this.root().symbolResolver().getRoot(); 26 | } 27 | 28 | @Override 29 | public void setSymbolResolver(SymbolResolver symbolResolver) { 30 | this.symbolResolver = symbolResolver; 31 | } 32 | 33 | private TypeResolver root; 34 | 35 | public TypeResolver root() { 36 | return root; 37 | } 38 | 39 | public void setRoot(TypeResolver root) { 40 | this.root = root; 41 | } 42 | 43 | public static JdkTypeResolver getInstance() { 44 | return INSTANCE; 45 | } 46 | 47 | @Override 48 | public Optional resolveAbsoluteTypeName(String typeName) { 49 | if (!JvmNameUtils.isValidQualifiedName(typeName)) { 50 | throw new IllegalArgumentException(typeName); 51 | } 52 | return ReflectionTypeDefinitionFactory.getInstance().findTypeDefinition(typeName, symbolResolver()); 53 | } 54 | 55 | @Override 56 | public Optional resolveAbsoluteFunctionName(String typeName) { 57 | return Optional.empty(); 58 | } 59 | 60 | @Override 61 | public boolean existPackage(String packageName) { 62 | return Package.getPackage(packageName) != null; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /turin-compiler/src/main/java/me/tomassetti/turin/resolvers/jdk/ReflectionBasedField.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.turin.resolvers.jdk; 2 | 3 | import me.tomassetti.jvm.JvmFieldDefinition; 4 | import me.tomassetti.turin.resolvers.SymbolResolver; 5 | import me.tomassetti.turin.symbols.Symbol; 6 | import me.tomassetti.turin.typesystem.TypeUsage; 7 | 8 | import java.lang.reflect.Field; 9 | import java.lang.reflect.Modifier; 10 | 11 | public class ReflectionBasedField implements Symbol { 12 | 13 | @Override 14 | public TypeUsage calcType() { 15 | return ReflectionTypeDefinitionFactory.toTypeUsage(field.getType(), symbolResolver); 16 | } 17 | 18 | @Override 19 | public Symbol getField(String fieldName) { 20 | TypeUsage fieldType = ReflectionTypeDefinitionFactory.toTypeUsage(field.getType(), symbolResolver); 21 | return fieldType.getInstanceField(fieldName, this); 22 | } 23 | 24 | @Override 25 | public boolean equals(Object o) { 26 | if (this == o) return true; 27 | if (o == null || getClass() != o.getClass()) return false; 28 | 29 | ReflectionBasedField that = (ReflectionBasedField) o; 30 | 31 | if (!field.equals(that.field)) return false; 32 | 33 | return true; 34 | } 35 | 36 | @Override 37 | public String toString() { 38 | return "ReflectionBaseField{" + 39 | "field=" + field + 40 | '}'; 41 | } 42 | 43 | @Override 44 | public int hashCode() { 45 | return field.hashCode(); 46 | } 47 | 48 | private Field field; 49 | private SymbolResolver symbolResolver; 50 | 51 | public ReflectionBasedField(Field field, SymbolResolver symbolResolver) { 52 | this.field = field; 53 | this.symbolResolver = symbolResolver; 54 | } 55 | 56 | public boolean isStatic() { 57 | return Modifier.isStatic(field.getModifiers()); 58 | } 59 | 60 | public JvmFieldDefinition toJvmField(SymbolResolver resolver) { 61 | TypeUsage fieldType = ReflectionTypeDefinitionFactory.toTypeUsage(field.getType(), symbolResolver); 62 | TypeUsage ownerType = ReflectionTypeDefinitionFactory.toTypeUsage(field.getDeclaringClass(), symbolResolver); 63 | return new JvmFieldDefinition(ownerType.jvmType().getInternalName(), field.getName(), fieldType.jvmType().getSignature(), true); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /turin-compiler/src/main/java/me/tomassetti/turin/symbols/FormalParameter.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.turin.symbols; 2 | 3 | import me.tomassetti.turin.typesystem.TypeUsage; 4 | 5 | import java.util.Map; 6 | 7 | public interface FormalParameter extends Symbol { 8 | 9 | boolean hasDefaultValue(); 10 | 11 | TypeUsage getType(); 12 | 13 | String getName(); 14 | 15 | FormalParameter apply(Map typeParams); 16 | } 17 | -------------------------------------------------------------------------------- /turin-compiler/src/main/java/me/tomassetti/turin/symbols/InvokableDefinition.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.turin.symbols; 2 | 3 | import me.tomassetti.turin.typesystem.TypeUsage; 4 | 5 | import java.util.List; 6 | 7 | public interface InvokableDefinition extends Symbol { 8 | TypeUsage getReturnType(); 9 | 10 | List getParameters(); 11 | 12 | String getName(); 13 | } 14 | -------------------------------------------------------------------------------- /turin-compiler/src/main/java/me/tomassetti/turin/symbols/Symbol.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.turin.symbols; 2 | 3 | import me.tomassetti.turin.parser.ast.Node; 4 | import me.tomassetti.turin.parser.ast.QualifiedName; 5 | import me.tomassetti.turin.parser.ast.expressions.InvokableExpr; 6 | import me.tomassetti.turin.typesystem.TypeUsage; 7 | 8 | import java.util.List; 9 | import java.util.Optional; 10 | 11 | /** 12 | * Something generic: it could come from an AST or be a loaded value. 13 | */ 14 | public interface Symbol { 15 | 16 | TypeUsage calcType(); 17 | 18 | /** 19 | * Is this symbol an AST node? 20 | */ 21 | default boolean isNode() { 22 | return false; 23 | } 24 | 25 | default Node asNode() { 26 | throw new UnsupportedOperationException(); 27 | } 28 | 29 | default Symbol getField(String fieldName) { 30 | throw new UnsupportedOperationException(this.getClass().getCanonicalName()); 31 | } 32 | 33 | default Symbol getField(QualifiedName fieldsPath) { 34 | if (fieldsPath.isSimpleName()) { 35 | return getField(fieldsPath.getName()); 36 | } else { 37 | Symbol next = getField(fieldsPath.firstSegment()); 38 | return next.getField(fieldsPath.rest()); 39 | } 40 | } 41 | 42 | default Optional> findFormalParametersFor(InvokableExpr invokable) { 43 | throw new UnsupportedOperationException(); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /turin-compiler/src/main/java/me/tomassetti/turin/typesystem/Invokable.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.turin.typesystem; 2 | 3 | import me.tomassetti.turin.definitions.InternalInvokableDefinition; 4 | import me.tomassetti.turin.parser.ast.expressions.ActualParam; 5 | 6 | import java.util.List; 7 | import java.util.Optional; 8 | 9 | /** 10 | * This represents something invokable. 11 | */ 12 | public interface Invokable { 13 | 14 | Optional internalInvokableDefinitionFor(List actualParams); 15 | 16 | boolean isOverloaded(); 17 | 18 | } 19 | -------------------------------------------------------------------------------- /turin-compiler/src/main/java/me/tomassetti/turin/typesystem/OverloadedFunctionReferenceTypeUsage.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.turin.typesystem; 2 | 3 | import java.util.List; 4 | 5 | public abstract class OverloadedFunctionReferenceTypeUsage implements TypeUsage, Invokable { 6 | 7 | protected List alternatives; 8 | 9 | OverloadedFunctionReferenceTypeUsage(List alternatives) { 10 | if (alternatives.size() < 2) { 11 | throw new IllegalArgumentException(); 12 | } 13 | this.alternatives = alternatives; 14 | } 15 | 16 | @Override 17 | public Invokable asInvokable() { 18 | return this; 19 | } 20 | 21 | @Override 22 | public boolean isInvokable() { 23 | return true; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /turin-compiler/src/main/java/me/tomassetti/turin/typesystem/VoidTypeUsage.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.turin.typesystem; 2 | 3 | import me.tomassetti.jvm.JvmType; 4 | import me.tomassetti.turin.symbols.Symbol; 5 | 6 | import java.util.Map; 7 | 8 | public class VoidTypeUsage implements TypeUsage { 9 | 10 | @Override 11 | public boolean isVoid() { 12 | return true; 13 | } 14 | 15 | @Override 16 | public String toString() { 17 | return "VoidTypeUsage{}"; 18 | } 19 | 20 | @Override 21 | public boolean equals(Object obj) { 22 | return obj instanceof VoidTypeUsage; 23 | } 24 | 25 | @Override 26 | public int hashCode() { 27 | return 127; 28 | } 29 | 30 | @Override 31 | public TypeUsage replaceTypeVariables(Map typeParams) { 32 | return this; 33 | } 34 | 35 | @Override 36 | public boolean sameType(TypeUsage other) { 37 | return other.isVoid(); 38 | } 39 | 40 | @Override 41 | public JvmType jvmType() { 42 | return new JvmType("V"); 43 | } 44 | 45 | @Override 46 | public boolean canBeAssignedTo(TypeUsage type) { 47 | return false; 48 | } 49 | 50 | @Override 51 | public Symbol getInstanceField(String fieldName, Symbol instance) { 52 | throw new UnsupportedOperationException(); 53 | } 54 | 55 | @Override 56 | public String describe() { 57 | return "void"; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /turin-compiler/src/main/java/me/tomassetti/turin/util/Either.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.turin.util; 2 | 3 | public class Either { 4 | 5 | private L left; 6 | 7 | public L getLeft() { 8 | if (!isLeft()) { 9 | throw new UnsupportedOperationException(); 10 | } 11 | return left; 12 | } 13 | 14 | public R getRight() { 15 | if (!isRight()) { 16 | throw new UnsupportedOperationException(); 17 | } 18 | return right; 19 | } 20 | 21 | public boolean isLeft() { 22 | return left != null; 23 | } 24 | 25 | public boolean isRight() { 26 | return right != null; 27 | } 28 | 29 | private R right; 30 | 31 | public static Either left(L left) { 32 | if (left == null) { 33 | throw new NullPointerException(); 34 | } 35 | return new Either(left, null); 36 | } 37 | 38 | public static Either right(R right) { 39 | if (right == null) { 40 | throw new NullPointerException(); 41 | } 42 | return new Either(null, right); 43 | } 44 | 45 | private Either(L left, R right) { 46 | this.left = left; 47 | this.right = right; 48 | } 49 | 50 | @Override 51 | public String toString() { 52 | if (left != null) { 53 | return "Either.left(" + left + ")"; 54 | } else { 55 | return "Either.right(" + right + ")"; 56 | } 57 | } 58 | 59 | @Override 60 | public boolean equals(Object o) { 61 | if (this == o) return true; 62 | if (!(o instanceof Either)) return false; 63 | 64 | Either either = (Either) o; 65 | 66 | if (left != null ? !left.equals(either.left) : either.left != null) return false; 67 | if (right != null ? !right.equals(either.right) : either.right != null) return false; 68 | 69 | return true; 70 | } 71 | 72 | @Override 73 | public int hashCode() { 74 | int result = left != null ? left.hashCode() : 0; 75 | result = 31 * result + (right != null ? right.hashCode() : 0); 76 | return result; 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /turin-compiler/src/main/java/me/tomassetti/turin/util/StringUtils.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.turin.util; 2 | 3 | public class StringUtils { 4 | 5 | public static String capitalize(String s) { 6 | if (s.isEmpty()) { 7 | return s; 8 | } 9 | if (s.length() == 1) { 10 | return s.toUpperCase(); 11 | } 12 | return s.substring(0, 1).toUpperCase() + s.substring(1); 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /turin-compiler/src/test/java/me/tomassetti/turin/compiler/ArrayAccessCompilationTest.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.turin.compiler; 2 | 3 | import me.tomassetti.turin.classloading.TurinClassLoader; 4 | import me.tomassetti.turin.classloading.ClassFileDefinition; 5 | import me.tomassetti.turin.parser.Parser; 6 | import me.tomassetti.turin.parser.ast.TurinFile; 7 | import org.junit.Test; 8 | 9 | import java.io.IOException; 10 | import java.lang.reflect.InvocationTargetException; 11 | import java.lang.reflect.Method; 12 | import java.util.List; 13 | 14 | import static org.junit.Assert.assertEquals; 15 | 16 | public class ArrayAccessCompilationTest extends AbstractCompilerTest { 17 | 18 | @Test 19 | public void compileArrayAccess() throws IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchMethodException, IOException { 20 | TurinFile turinFile = new Parser().parse(this.getClass().getResourceAsStream("/array_access.to")); 21 | 22 | // generate bytecode 23 | Compiler instance = new Compiler(getResolverFor(turinFile), new Compiler.Options()); 24 | List classFileDefinitions = instance.compile(turinFile, new MyErrorCollector()); 25 | assertEquals(1, classFileDefinitions.size()); 26 | 27 | TurinClassLoader turinClassLoader = new TurinClassLoader(); 28 | Class functionClass = turinClassLoader.addClass(classFileDefinitions.get(0).getName(), 29 | classFileDefinitions.get(0).getBytecode()); 30 | 31 | Method getByIndex = functionClass.getMethod("invoke", int[].class, int.class); 32 | assertEquals(27, getByIndex.invoke(null, new int[]{27, 29, 4}, 0)); 33 | assertEquals(29, getByIndex.invoke(null, new int[]{27, 29, 4}, 1)); 34 | assertEquals(4, getByIndex.invoke(null, new int[]{27, 29, 4}, 2)); 35 | } 36 | 37 | } 38 | 39 | -------------------------------------------------------------------------------- /turin-compiler/src/test/java/me/tomassetti/turin/compiler/CompileArrayOperationsTest.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.turin.compiler; 2 | 3 | import org.junit.Test; 4 | 5 | import java.io.IOException; 6 | import java.lang.reflect.InvocationTargetException; 7 | import java.lang.reflect.Method; 8 | 9 | import static org.junit.Assert.assertEquals; 10 | 11 | public class CompileArrayOperationsTest extends AbstractCompilerTest { 12 | 13 | @Test 14 | public void compileArrayLength() throws IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchMethodException, IOException { 15 | Method invoke = compileFunction("array_length", new Class[]{int[].class}); 16 | assertEquals(0, invoke.invoke(null, new int[]{})); 17 | assertEquals(1, invoke.invoke(null, new int[]{1})); 18 | assertEquals(3, invoke.invoke(null, new int[]{1, 2, 3})); 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /turin-compiler/src/test/java/me/tomassetti/turin/compiler/ReferenceToCaughtExceptionCompilationTest.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.turin.compiler; 2 | 3 | import org.junit.Test; 4 | 5 | import java.io.IOException; 6 | import java.lang.reflect.InvocationTargetException; 7 | import java.lang.reflect.Method; 8 | 9 | import static org.junit.Assert.assertEquals; 10 | 11 | public class ReferenceToCaughtExceptionCompilationTest extends AbstractCompilerTest { 12 | 13 | @Test 14 | public void referenceToCaughtExceptionCompilation() throws IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchMethodException, IOException { 15 | Method invoke = compileFunction("reference_to_caught_exception", new Class[]{}); 16 | assertEquals("abcdef", invoke.invoke(null)); 17 | } 18 | 19 | } 20 | 21 | -------------------------------------------------------------------------------- /turin-compiler/src/test/java/me/tomassetti/turin/compiler/ReferenceToLocalVarCompilationTest.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.turin.compiler; 2 | 3 | import me.tomassetti.turin.classloading.TurinClassLoader; 4 | import me.tomassetti.turin.classloading.ClassFileDefinition; 5 | import me.tomassetti.turin.parser.Parser; 6 | import me.tomassetti.turin.parser.ast.TurinFile; 7 | import org.junit.Test; 8 | 9 | import java.io.IOException; 10 | import java.lang.reflect.InvocationTargetException; 11 | import java.lang.reflect.Method; 12 | import java.util.List; 13 | 14 | import static org.junit.Assert.*; 15 | 16 | public class ReferenceToLocalVarCompilationTest extends AbstractCompilerTest { 17 | 18 | @Test 19 | public void compile() throws IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchMethodException, IOException { 20 | TurinFile turinFile = new Parser().parse(this.getClass().getResourceAsStream("/reference_to_localvar.to")); 21 | 22 | // generate bytecode 23 | Compiler instance = new Compiler(getResolverFor(turinFile), new Compiler.Options()); 24 | List classFileDefinitions = instance.compile(turinFile, new MyErrorCollector()); 25 | assertEquals(2, classFileDefinitions.size()); 26 | 27 | TurinClassLoader turinClassLoader = new TurinClassLoader(); 28 | Class typeClass = turinClassLoader.addClass(classFileDefinitions.get(0).getName(), 29 | classFileDefinitions.get(0).getBytecode()); 30 | Class functionClass = turinClassLoader.addClass(classFileDefinitions.get(1).getName(), 31 | classFileDefinitions.get(1).getBytecode()); 32 | 33 | Method invoke = functionClass.getMethod("invoke"); 34 | Object result = invoke.invoke(null); 35 | Method newLinesAfterLBracket = result.getClass().getDeclaredMethod("isNewLinesAfterLBracket"); 36 | Method indentationSize = result.getClass().getDeclaredMethod("getIndentationSize"); 37 | assertEquals(true, newLinesAfterLBracket.invoke(result)); 38 | assertEquals(4, indentationSize.invoke(result)); 39 | } 40 | 41 | } 42 | 43 | -------------------------------------------------------------------------------- /turin-compiler/src/test/java/me/tomassetti/turin/compiler/ReferenceToStaticFieldInCompiledClassCompilationTest.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.turin.compiler; 2 | 3 | import org.junit.Test; 4 | 5 | import java.io.IOException; 6 | import java.lang.reflect.InvocationTargetException; 7 | import java.lang.reflect.Method; 8 | import java.nio.charset.Charset; 9 | import java.nio.charset.StandardCharsets; 10 | 11 | import static org.junit.Assert.assertEquals; 12 | import static org.junit.Assert.assertTrue; 13 | 14 | public class ReferenceToStaticFieldInCompiledClassCompilationTest extends AbstractCompilerTest { 15 | @Test 16 | public void compile() throws IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchMethodException, IOException { 17 | Method method = compileFunction("reference_to_static_field_compiled", new Class[]{}); 18 | Object result = method.invoke(null); 19 | assertTrue(result instanceof Charset); 20 | assertEquals(result, StandardCharsets.UTF_8); 21 | } 22 | 23 | } 24 | -------------------------------------------------------------------------------- /turin-compiler/src/test/java/me/tomassetti/turin/compiler/StaticMethodsInvokationCompilationTest.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.turin.compiler; 2 | 3 | import me.tomassetti.turin.classloading.TurinClassLoader; 4 | import me.tomassetti.turin.classloading.ClassFileDefinition; 5 | import me.tomassetti.turin.parser.Parser; 6 | import me.tomassetti.turin.parser.ast.TurinFile; 7 | import org.junit.Test; 8 | 9 | import java.io.IOException; 10 | import java.lang.reflect.InvocationTargetException; 11 | import java.lang.reflect.Method; 12 | import java.util.List; 13 | 14 | import static org.junit.Assert.assertEquals; 15 | import static org.junit.Assert.assertTrue; 16 | 17 | public class StaticMethodsInvokationCompilationTest extends AbstractCompilerTest { 18 | 19 | @Test 20 | public void compileInvokationsToCollectionsEmptyList() throws IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchMethodException, IOException { 21 | TurinFile turinFile = new Parser().parse(this.getClass().getResourceAsStream("/static_methods_invokation.to")); 22 | 23 | // generate bytecode 24 | Compiler instance = new Compiler(getResolverFor(turinFile), new Compiler.Options()); 25 | List classFileDefinitions = instance.compile(turinFile, new MyErrorCollector()); 26 | assertEquals(1, classFileDefinitions.size()); 27 | 28 | TurinClassLoader turinClassLoader = new TurinClassLoader(); 29 | Class functionClass = turinClassLoader.addClass(classFileDefinitions.get(0).getName(), 30 | classFileDefinitions.get(0).getBytecode()); 31 | assertEquals(0, functionClass.getConstructors().length); 32 | 33 | Method invoke = functionClass.getMethod("invoke"); 34 | Object result = invoke.invoke(null); 35 | assertTrue(result instanceof List); 36 | List list = (List)result; 37 | assertTrue(list.isEmpty()); 38 | } 39 | 40 | } 41 | 42 | -------------------------------------------------------------------------------- /turin-compiler/src/test/java/me/tomassetti/turin/compiler/TopLevelFunctionInvokationCompilationTest.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.turin.compiler; 2 | 3 | import me.tomassetti.turin.classloading.TurinClassLoader; 4 | import me.tomassetti.turin.classloading.ClassFileDefinition; 5 | import me.tomassetti.turin.parser.Parser; 6 | import me.tomassetti.turin.parser.ast.TurinFile; 7 | import org.junit.Test; 8 | 9 | import java.io.IOException; 10 | import java.lang.reflect.InvocationTargetException; 11 | import java.lang.reflect.Method; 12 | import java.util.List; 13 | 14 | import static org.junit.Assert.assertEquals; 15 | 16 | public class TopLevelFunctionInvokationCompilationTest extends AbstractCompilerTest { 17 | 18 | @Test 19 | public void referenceToCaughtExceptionCompilation() throws IllegalAccessException, InvocationTargetException, InstantiationException, NoSuchMethodException, IOException { 20 | TurinFile turinFile = new Parser().parse(this.getClass().getResourceAsStream("/function_reference.to")); 21 | 22 | // generate bytecode 23 | Compiler.Options options = new Compiler.Options(); 24 | Compiler instance = new Compiler(getResolverFor(turinFile), options); 25 | List classFileDefinitions = instance.compile(turinFile, new MyErrorCollector()); 26 | assertEquals(2, classFileDefinitions.size()); 27 | 28 | TurinClassLoader turinClassLoader = new TurinClassLoader(); 29 | Class foo1Class = turinClassLoader.addClass(classFileDefinitions.get(0).getName(), 30 | classFileDefinitions.get(0).getBytecode()); 31 | Class foo2Class = turinClassLoader.addClass(classFileDefinitions.get(1).getName(), 32 | classFileDefinitions.get(1).getBytecode()); 33 | 34 | Method invoke1 = foo1Class.getMethod("invoke"); 35 | Method invoke2 = foo2Class.getMethod("invoke"); 36 | 37 | assertEquals("foo1", invoke1.invoke(null)); 38 | assertEquals("foo1", invoke2.invoke(null)); 39 | } 40 | 41 | } 42 | 43 | -------------------------------------------------------------------------------- /turin-compiler/src/test/java/me/tomassetti/turin/parser/ast/TypeDefinitionTest.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.turin.parser.ast; 2 | 3 | public class TypeDefinitionTest { 4 | 5 | } 6 | -------------------------------------------------------------------------------- /turin-compiler/src/test/java/me/tomassetti/turin/typesystem/VoidTypeUsageTest.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.turin.typesystem; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.assertEquals; 6 | 7 | public class VoidTypeUsageTest { 8 | 9 | @Test 10 | public void testIsArray() { 11 | assertEquals(false, new VoidTypeUsage().isArray()); 12 | } 13 | 14 | @Test 15 | public void testIsPrimitive() { 16 | assertEquals(false, new VoidTypeUsage().isPrimitive()); 17 | } 18 | 19 | @Test 20 | public void testIsReferenceTypeUsage() { 21 | assertEquals(false, new VoidTypeUsage().isReferenceTypeUsage()); 22 | } 23 | 24 | @Test 25 | public void testIsVoid() { 26 | assertEquals(true, new VoidTypeUsage().isVoid()); 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /turin-compiler/src/test/java/me/tomassetti/turin/util/EitherTest.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.turin.util; 2 | 3 | import org.junit.Test; 4 | 5 | import static org.junit.Assert.*; 6 | 7 | public class EitherTest { 8 | 9 | Either ok = Either.right("ok"); 10 | Either ko = Either.left("ko"); 11 | 12 | @Test 13 | public void getRightPositive() { 14 | assertEquals("ok", ok.getRight()); 15 | } 16 | 17 | @Test(expected = UnsupportedOperationException.class) 18 | public void getRightNegative() { 19 | ko.getRight(); 20 | } 21 | 22 | @Test 23 | public void getLeftPositive() { 24 | assertEquals("ko", ko.getLeft()); 25 | } 26 | 27 | @Test(expected = UnsupportedOperationException.class) 28 | public void getLeftNegative() { 29 | ok.getLeft(); 30 | } 31 | 32 | @Test 33 | public void testIsLeft() { 34 | assertEquals(false, ok.isLeft()); 35 | assertEquals(true, ko.isLeft()); 36 | } 37 | 38 | @Test 39 | public void testIsRight() { 40 | assertEquals(true, ok.isRight()); 41 | assertEquals(false, ko.isRight()); 42 | } 43 | 44 | @Test 45 | public void testToString() { 46 | assertEquals("Either.right(ok)", ok.toString()); 47 | assertEquals("Either.left(ko)", ko.toString()); 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /turin-compiler/src/test/resources/annotations.to: -------------------------------------------------------------------------------- 1 | namespace annotations 2 | 3 | import turin.test.Test 4 | 5 | @Test 6 | int getByIndex(int[] array, int index) = array[index] 7 | 8 | @Test 9 | type A { 10 | } 11 | -------------------------------------------------------------------------------- /turin-compiler/src/test/resources/array_access.to: -------------------------------------------------------------------------------- 1 | namespace manga 2 | 3 | int getByIndex(int[] array, int index) = array[index] 4 | -------------------------------------------------------------------------------- /turin-compiler/src/test/resources/array_length.to: -------------------------------------------------------------------------------- 1 | namespace manga 2 | 3 | int l(int[] array) = array.length 4 | -------------------------------------------------------------------------------- /turin-compiler/src/test/resources/bad_usage_of_asterisk_on_creation1.to: -------------------------------------------------------------------------------- 1 | namespace manga 2 | 3 | type Foo { 4 | int a 5 | int b = 10 6 | int c default 5 7 | int d default 7 8 | } 9 | 10 | Foo foo1() = Foo(1, *=Foo(1)) 11 | 12 | -------------------------------------------------------------------------------- /turin-compiler/src/test/resources/bad_usage_of_asterisk_on_creation2.to: -------------------------------------------------------------------------------- 1 | namespace manga 2 | 3 | type Foo { 4 | int a 5 | int b = 10 6 | int c default 5 7 | int d default 7 8 | } 9 | 10 | Foo foo2() = Foo(a=1, *=Foo(1)) 11 | 12 | -------------------------------------------------------------------------------- /turin-compiler/src/test/resources/bad_usage_of_asterisk_on_creation3.to: -------------------------------------------------------------------------------- 1 | namespace manga 2 | 3 | type Foo { 4 | int a 5 | int b = 10 6 | int c default 5 7 | int d default 7 8 | } 9 | 10 | StringBuilder foo3() = StringBuilder(*=Foo()) 11 | 12 | -------------------------------------------------------------------------------- /turin-compiler/src/test/resources/bad_usage_of_asterisk_on_method1.to: -------------------------------------------------------------------------------- 1 | namespace manga 2 | 3 | type Foo { 4 | int a 5 | int b = 10 6 | int c default 5 7 | int d default 7 8 | } 9 | 10 | Foo foo2() = StringBuilder().append(*=Foo()) 11 | 12 | -------------------------------------------------------------------------------- /turin-compiler/src/test/resources/basicManga.to: -------------------------------------------------------------------------------- 1 | namespace manga 2 | 3 | property String name 4 | 5 | type MangaCharacter { 6 | has name 7 | uint age 8 | } 9 | -------------------------------------------------------------------------------- /turin-compiler/src/test/resources/boolean_literals.to: -------------------------------------------------------------------------------- 1 | namespace examples 2 | 3 | type A { 4 | boolean foo1() = false 5 | boolean foo2() = true 6 | } 7 | 8 | -------------------------------------------------------------------------------- /turin-compiler/src/test/resources/call_void_function.to: -------------------------------------------------------------------------------- 1 | namespace foo 2 | 3 | void foo() { 4 | } 5 | 6 | program A(String[] args) { 7 | foo() 8 | } 9 | -------------------------------------------------------------------------------- /turin-compiler/src/test/resources/common_methods.to: -------------------------------------------------------------------------------- 1 | namespace manga 2 | 3 | type A { 4 | String toString() = "foo" 5 | } 6 | 7 | type B { 8 | String toString(int i) = "unrelated toString!" 9 | } 10 | 11 | type C { 12 | int hashCode() = 1 13 | } 14 | 15 | type D { 16 | int hashCode(String s) = 1 17 | Boolean equals(Object o) = false 18 | } 19 | 20 | type E { 21 | int hashCode(String s) = 1 22 | Boolean equals(String s) = true 23 | } 24 | -------------------------------------------------------------------------------- /turin-compiler/src/test/resources/context/context_definition.to: -------------------------------------------------------------------------------- 1 | namespace a 2 | 3 | context int a 4 | context String b 5 | 6 | 7 | -------------------------------------------------------------------------------- /turin-compiler/src/test/resources/context/context_usage.to: -------------------------------------------------------------------------------- 1 | namespace a 2 | 3 | import java.util.Optional 4 | 5 | context String worldName 6 | 7 | Optional[String] worldNameInCtx() { 8 | context (worldName="Earth") { 9 | return context.worldName 10 | } 11 | } 12 | 13 | Optional[String] worldNameNoCtx() = context.worldName 14 | 15 | -------------------------------------------------------------------------------- /turin-compiler/src/test/resources/default_values.to: -------------------------------------------------------------------------------- 1 | namespace foo 2 | 3 | type Foo { 4 | int a 5 | int b = 10 6 | int c default 5 7 | int d default 7 8 | } 9 | 10 | Foo foo1() = Foo(1, 2, 3) 11 | Foo foo2() = Foo(1, 2) 12 | Foo foo3() = Foo(1, d=3) 13 | Foo foo4() = Foo(1, d=3, c=2) 14 | -------------------------------------------------------------------------------- /turin-compiler/src/test/resources/duplicate_functions.to: -------------------------------------------------------------------------------- 1 | namespace foo 2 | 3 | void bar() { 4 | } 5 | 6 | void bar(int i) { 7 | } 8 | -------------------------------------------------------------------------------- /turin-compiler/src/test/resources/duplicate_programs.to: -------------------------------------------------------------------------------- 1 | namespace foo 2 | 3 | program Baz(String[] args) { 4 | } 5 | 6 | program Baz(String[] args) { 7 | } 8 | -------------------------------------------------------------------------------- /turin-compiler/src/test/resources/duplicate_types.to: -------------------------------------------------------------------------------- 1 | namespace foo 2 | 3 | type Baz { 4 | } 5 | 6 | type Baz { 7 | } 8 | -------------------------------------------------------------------------------- /turin-compiler/src/test/resources/examples/formatter1.to: -------------------------------------------------------------------------------- 1 | namespace me.tomassetti.javaformatter 2 | 3 | import java.lang.System.out.println as print 4 | import java.lang.System.err.println as eprint 5 | import com.github.javaparser.ast.CompilationUnit 6 | 7 | void fatalError(String msg) { 8 | eprint(msg) 9 | System.exit(1) 10 | } 11 | 12 | CompilationUnit parse(String path) { 13 | throw UnsupportedOperationException("To be implemented") 14 | } 15 | 16 | program JavaFormatter(String[] args) { 17 | print("Java Formatter v0.1") 18 | if args.length != 1 { 19 | fatalError("pass exactly one parameter") 20 | } 21 | try { 22 | val cu = parse(args[0]) 23 | } catch Exception e { 24 | fatalError("Issue parsing #{args[0]}: #{e.getMessage()}") 25 | } 26 | throw UnsupportedOperationException("To be implemented") 27 | } 28 | -------------------------------------------------------------------------------- /turin-compiler/src/test/resources/examples/formatter2.to: -------------------------------------------------------------------------------- 1 | namespace me.tomassetti.javaformatter 2 | 3 | import java.lang.System.out.println as print 4 | import java.lang.System.err.println as eprint 5 | import com.github.javaparser.ast.CompilationUnit 6 | import com.github.javaparser.JavaParser 7 | import java.io.File 8 | 9 | void fatalError(String msg) { 10 | eprint(msg) 11 | System.exit(1) 12 | } 13 | 14 | CompilationUnit parse(String path) { 15 | //throw UnsupportedOperationException("To be implemented") 16 | return JavaParser.parse(File(path)) 17 | } 18 | 19 | program JavaFormatter(String[] args) { 20 | val debug = true 21 | print("Java Formatter v0.1") 22 | if args.length != 1 { 23 | fatalError("pass exactly one parameter") 24 | } 25 | try { 26 | val cu = parse(args[0]) 27 | if debug { 28 | print("Parsed correctly") 29 | } 30 | } catch Exception e { 31 | fatalError("Issue parsing #{args[0]}: #{e.getMessage()}") 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /turin-compiler/src/test/resources/examples/formatter3.to: -------------------------------------------------------------------------------- 1 | namespace me.tomassetti.javaformatter 2 | 3 | import java.lang.System.out.println as print 4 | import java.lang.System.err.println as eprint 5 | import com.github.javaparser.ast.CompilationUnit 6 | import com.github.javaparser.JavaParser 7 | import java.io.* 8 | 9 | type Options { 10 | boolean newLinesAfterLBracket default false 11 | boolean useTabs default false 12 | int indentationSize default 4 : _ >= 1 and _ <= 20 | "#{_name} should be between 1 and 20, instead it is #{_}" 13 | } 14 | 15 | void fatalError(String msg) { 16 | eprint(msg) 17 | System.exit(1) 18 | } 19 | 20 | CompilationUnit parse(String path) { 21 | //throw UnsupportedOperationException("To be implemented") 22 | return JavaParser.parse(File(path)) 23 | } 24 | 25 | String format(CompilationUnit cu) { 26 | val sw = StringWriter() 27 | val pw = PrintWriter(sw) 28 | 29 | pw.print(cu) 30 | 31 | return sw.toString() 32 | } 33 | 34 | program JavaFormatter(String[] args) { 35 | val options = Options(newLinesAfterLBracket=true) 36 | print(options) 37 | val debug = true 38 | print("Java Formatter v0.1") 39 | if args.length != 1 { 40 | fatalError("pass exactly one parameter") 41 | } 42 | try { 43 | val cu = parse(args[0]) 44 | if debug { 45 | print("Parsed correctly") 46 | } 47 | print("OUTPUT:") 48 | print(format(cu)) 49 | } catch Exception e { 50 | fatalError("Issue parsing #{args[0]}: #{e.getMessage()}") 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /turin-compiler/src/test/resources/explicit_constructor_no_extend.to: -------------------------------------------------------------------------------- 1 | namespace explicit_constructors 2 | 3 | type A { 4 | 5 | String a 6 | 7 | init(int a) { 8 | this.a = Integer.toString(a) 9 | } 10 | 11 | } 12 | -------------------------------------------------------------------------------- /turin-compiler/src/test/resources/explicit_constructors.to: -------------------------------------------------------------------------------- 1 | namespace explicit_constructors 2 | 3 | type A { 4 | 5 | init(String a) { 6 | } 7 | 8 | init(int a) { 9 | } 10 | 11 | } 12 | -------------------------------------------------------------------------------- /turin-compiler/src/test/resources/field_constraints_on_default_param.to: -------------------------------------------------------------------------------- 1 | namespace field_constraints 2 | 3 | type Options { 4 | int indentationSize default 4 : _ >= 1 and _ <= 20 | "#{_name} should be between 1 and 20, instead it is #{_}" 5 | } 6 | 7 | void foo1() { 8 | Options(indentationSize=0) 9 | } 10 | 11 | void foo2() { 12 | Options(indentationSize=-10) 13 | } 14 | 15 | void foo3() { 16 | Options(indentationSize=50) 17 | } 18 | 19 | void foo4() { 20 | Options(indentationSize=10) 21 | } 22 | 23 | void foo5() { 24 | Options(indentationSize=10).setIndentationSize(-2) 25 | } 26 | 27 | void foo6() { 28 | Options(indentationSize=10).setIndentationSize(2) 29 | } 30 | -------------------------------------------------------------------------------- /turin-compiler/src/test/resources/field_constraints_on_non_default_param.to: -------------------------------------------------------------------------------- 1 | namespace field_constraints 2 | 3 | type Options { 4 | int indentationSize : _ >= 1 and _ <= 20 | "#{_name} should be between 1 and 20, instead it is #{_}" 5 | } 6 | 7 | void foo1() { 8 | Options(indentationSize=0) 9 | } 10 | 11 | void foo2() { 12 | Options(indentationSize=-10) 13 | } 14 | 15 | void foo3() { 16 | Options(indentationSize=50) 17 | } 18 | 19 | void foo4() { 20 | Options(indentationSize=10) 21 | } 22 | 23 | void foo5() { 24 | Options(indentationSize=10).setIndentationSize(-2) 25 | } 26 | 27 | void foo6() { 28 | Options(indentationSize=10).setIndentationSize(2) 29 | } 30 | -------------------------------------------------------------------------------- /turin-compiler/src/test/resources/function_reference.to: -------------------------------------------------------------------------------- 1 | namespace foo 2 | 3 | String foo1() = "foo1" 4 | 5 | String foo2() = foo1() 6 | -------------------------------------------------------------------------------- /turin-compiler/src/test/resources/function_with_block_body.to: -------------------------------------------------------------------------------- 1 | namespace foo 2 | 3 | int sum(int a, int b) { 4 | return a + b 5 | } 6 | -------------------------------------------------------------------------------- /turin-compiler/src/test/resources/function_with_expression_body.to: -------------------------------------------------------------------------------- 1 | namespace foo 2 | 3 | String toString() = "foo" 4 | -------------------------------------------------------------------------------- /turin-compiler/src/test/resources/if.to: -------------------------------------------------------------------------------- 1 | namespace examples 2 | 3 | type A { 4 | 5 | String foo1(boolean a) { 6 | if a { 7 | return "A" 8 | } 9 | return "B" 10 | } 11 | 12 | String foo2(boolean a) { 13 | if a { 14 | return "A" 15 | } else { 16 | return "B" 17 | } 18 | } 19 | 20 | String foo3(boolean a, boolean b, boolean c) { 21 | if a { 22 | return "A" 23 | } elif b { 24 | return "B" 25 | } elif c { 26 | return "C" 27 | } else { 28 | return "D" 29 | } 30 | } 31 | 32 | String foo4(boolean a, boolean b, boolean c) { 33 | if a { 34 | return "A" 35 | } elif b { 36 | return "B" 37 | } elif c { 38 | return "C" 39 | } 40 | return "D" 41 | } 42 | 43 | } 44 | 45 | -------------------------------------------------------------------------------- /turin-compiler/src/test/resources/importOfAllFieldsInType.to: -------------------------------------------------------------------------------- 1 | namespace imports 2 | 3 | import java.lang.System.* 4 | 5 | Object foo() = out 6 | -------------------------------------------------------------------------------- /turin-compiler/src/test/resources/importOfAllFieldsInUnexistingType.to: -------------------------------------------------------------------------------- 1 | namespace imports 2 | 3 | import java.lang.SystemUnexisting.* 4 | -------------------------------------------------------------------------------- /turin-compiler/src/test/resources/importOfFieldsInTypeWithAlias.to: -------------------------------------------------------------------------------- 1 | namespace imports 2 | 3 | import java.lang.System.out as o 4 | 5 | Object foo() = o 6 | -------------------------------------------------------------------------------- /turin-compiler/src/test/resources/importOfFieldsInTypeWithoutAlias.to: -------------------------------------------------------------------------------- 1 | namespace imports 2 | 3 | import java.lang.System.out 4 | 5 | Object foo() = out 6 | -------------------------------------------------------------------------------- /turin-compiler/src/test/resources/importOfTypeWithAlias.to: -------------------------------------------------------------------------------- 1 | namespace imports 2 | 3 | import java.util.LinkedList as LL 4 | 5 | java.util.List[String] foo() = LL[String]() 6 | -------------------------------------------------------------------------------- /turin-compiler/src/test/resources/importOfTypeWithoutAlias.to: -------------------------------------------------------------------------------- 1 | namespace imports 2 | 3 | import java.util.LinkedList 4 | 5 | java.util.List[String] foo() = LinkedList[String]() 6 | -------------------------------------------------------------------------------- /turin-compiler/src/test/resources/importOfTypesFromUnexistingPackage.to: -------------------------------------------------------------------------------- 1 | namespace imports 2 | 3 | import foo.unexisting.* 4 | -------------------------------------------------------------------------------- /turin-compiler/src/test/resources/importOfTypesInPackage.to: -------------------------------------------------------------------------------- 1 | namespace imports 2 | 3 | import java.util.* 4 | 5 | List[String] foo() = LinkedList[String]() 6 | -------------------------------------------------------------------------------- /turin-compiler/src/test/resources/importOfUnexistingField.to: -------------------------------------------------------------------------------- 1 | namespace imports 2 | 3 | import java.lang.System.baz 4 | -------------------------------------------------------------------------------- /turin-compiler/src/test/resources/importOfUnexistingType.to: -------------------------------------------------------------------------------- 1 | namespace imports 2 | 3 | import java.lang.SystemBaz 4 | -------------------------------------------------------------------------------- /turin-compiler/src/test/resources/import_date_with_alias.to: -------------------------------------------------------------------------------- 1 | namespace examples 2 | 3 | import java.util.Date as D 4 | 5 | program Example(String[] args) { 6 | val d = D() 7 | } 8 | -------------------------------------------------------------------------------- /turin-compiler/src/test/resources/import_date_with_asterisk.to: -------------------------------------------------------------------------------- 1 | namespace examples 2 | 3 | import java.util.* 4 | 5 | program Example(String[] args) { 6 | val d = Date() 7 | } 8 | -------------------------------------------------------------------------------- /turin-compiler/src/test/resources/import_date_without_asterisk.to: -------------------------------------------------------------------------------- 1 | namespace examples 2 | 3 | import java.util.Date 4 | 5 | program Example(String[] args) { 6 | val d = Date() 7 | } 8 | -------------------------------------------------------------------------------- /turin-compiler/src/test/resources/initial_values.to: -------------------------------------------------------------------------------- 1 | namespace foo 2 | 3 | type Foo { 4 | int a 5 | int b = 10 6 | int c = 12 7 | int d 8 | } 9 | 10 | Foo foo1() = Foo(1, 2) 11 | -------------------------------------------------------------------------------- /turin-compiler/src/test/resources/instantiation_of_date.to: -------------------------------------------------------------------------------- 1 | namespace examples 2 | 3 | program Example(String[] args) { 4 | val d = java.util.Date() 5 | } 6 | -------------------------------------------------------------------------------- /turin-compiler/src/test/resources/jars/javaparser-core-2.2.1.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ftomassetti/turin-programming-language/ae4aa23f92727a28479c99c3fd79b6c6d73fdd20/turin-compiler/src/test/resources/jars/javaparser-core-2.2.1.jar -------------------------------------------------------------------------------- /turin-compiler/src/test/resources/jars/junit-4.12.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ftomassetti/turin-programming-language/ae4aa23f92727a28479c99c3fd79b6c6d73fdd20/turin-compiler/src/test/resources/jars/junit-4.12.jar -------------------------------------------------------------------------------- /turin-compiler/src/test/resources/logical_operators.to: -------------------------------------------------------------------------------- 1 | namespace examples 2 | 3 | type A { 4 | boolean foo1() = false and false 5 | boolean foo2() = false and true 6 | boolean foo3() = true and false 7 | boolean foo4() = true and true 8 | boolean foo5() = false or false 9 | boolean foo6() = false or true 10 | boolean foo7() = true or false 11 | boolean foo8() = true or true 12 | boolean foo9() = not false 13 | boolean foo10() = not true 14 | boolean foo11() = not false or not true 15 | boolean foo12() = not ((false or true) or false) 16 | } 17 | 18 | -------------------------------------------------------------------------------- /turin-compiler/src/test/resources/manga.to: -------------------------------------------------------------------------------- 1 | namespace manga 2 | 3 | property String name 4 | 5 | type MangaCharacter { 6 | has name 7 | uint age 8 | } 9 | 10 | program MangaExample(String[] args) { 11 | val ranma = MangaCharacter("Ranma", 16) 12 | print("The protagonist is #{ranma}") 13 | } 14 | -------------------------------------------------------------------------------- /turin-compiler/src/test/resources/manga_with_methods.to: -------------------------------------------------------------------------------- 1 | namespace manga 2 | 3 | import java.lang.System.out.println as print 4 | 5 | property String name 6 | 7 | type MangaCharacter { 8 | has name 9 | uint age 10 | 11 | String toString() = "#{name}, #{age}" 12 | } 13 | 14 | program MangaExample(String[] args) { 15 | val ranma = MangaCharacter("Ranma", 16) 16 | print("The protagonist is #{ranma}") 17 | } 18 | -------------------------------------------------------------------------------- /turin-compiler/src/test/resources/math.to: -------------------------------------------------------------------------------- 1 | namespace examples 2 | 3 | type Math { 4 | int b 5 | int c 6 | int calc(int a) = a + b * c 7 | } 8 | -------------------------------------------------------------------------------- /turin-compiler/src/test/resources/ok_usage_of_asterisk_in_creation_with_object.to: -------------------------------------------------------------------------------- 1 | namespace manga 2 | 3 | type Foo { 4 | int a 5 | int b = 10 6 | int c default 5 7 | int d default 7 8 | } 9 | 10 | Foo foo1() = Foo(*=Foo(1)) 11 | Foo foo2() = Foo(*=Foo(1, 15)) 12 | Foo foo3() = Foo(*=Foo(1, d=15)) 13 | 14 | 15 | -------------------------------------------------------------------------------- /turin-compiler/src/test/resources/ok_usage_of_asterisk_in_method_with_object.to: -------------------------------------------------------------------------------- 1 | namespace manga 2 | 3 | type Foo { 4 | int a 5 | int b = 10 6 | int c default 5 7 | int d default 7 8 | } 9 | 10 | Foo callMe(int a, int c) = Foo(a, c) 11 | 12 | Foo foo1() { 13 | val foo = Foo(1) 14 | foo.setA(*=Foo(23)) 15 | return foo 16 | } 17 | 18 | Foo foo2() = callMe(*=Foo(1, 15)) 19 | Foo foo3() = callMe(*=Foo(1, d=15)) 20 | 21 | -------------------------------------------------------------------------------- /turin-compiler/src/test/resources/parser_examples/type_extending_and_implementing.to: -------------------------------------------------------------------------------- 1 | namespace foo.bar 2 | 3 | type A extends Object implements Serializable, Cloneable { 4 | } 5 | -------------------------------------------------------------------------------- /turin-compiler/src/test/resources/primitive_data.to: -------------------------------------------------------------------------------- 1 | namespace examples 2 | 3 | type UseBoolean { 4 | boolean b 5 | String toString() = "#{b}" 6 | } 7 | 8 | type UseChar { 9 | char c 10 | String toString() = "#{c}" 11 | } 12 | 13 | type UseByte { 14 | byte b 15 | String toString() = "#{b}" 16 | } 17 | 18 | type UseShort { 19 | short s 20 | String toString() = "#{s}" 21 | } 22 | 23 | type UseInt { 24 | int i 25 | String toString() = "#{i}" 26 | } 27 | 28 | type UseLong { 29 | long l 30 | String toString() = "#{l}" 31 | } 32 | 33 | type UseFloat { 34 | float f 35 | String toString() = "#{f}" 36 | } 37 | 38 | type UseDouble { 39 | double d 40 | String toString() = "#{d}" 41 | } 42 | -------------------------------------------------------------------------------- /turin-compiler/src/test/resources/ranma.to: -------------------------------------------------------------------------------- 1 | namespace manga 2 | 3 | import java.lang.System.out.println as print 4 | 5 | property String name 6 | 7 | type MangaCharacter { 8 | has name 9 | uint age 10 | } 11 | 12 | program MangaExample(String[] args) { 13 | val ranma = MangaCharacter("Ranma", 16) 14 | print("The protagonist is #{ranma}") 15 | //print("The protagonist is " + ranma.name) 16 | } 17 | -------------------------------------------------------------------------------- /turin-compiler/src/test/resources/ref_to_function_in_classes.to: -------------------------------------------------------------------------------- 1 | namespace me.tomassetti.javaformatter 2 | 3 | void foo() { 4 | fatalError("Not using Turin!") 5 | } 6 | -------------------------------------------------------------------------------- /turin-compiler/src/test/resources/reference_to_caught_exception.to: -------------------------------------------------------------------------------- 1 | namespace foo 2 | 3 | String foo() { 4 | try { 5 | throw RuntimeException("abcdef") 6 | } catch RuntimeException e { 7 | return e.getMessage() 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /turin-compiler/src/test/resources/reference_to_localvar.to: -------------------------------------------------------------------------------- 1 | namespace reftolocalvar 2 | 3 | type Options { 4 | boolean newLinesAfterLBracket default false 5 | boolean useTabs default false 6 | int indentationSize default 4 : _ >= 1 and _ <= 20 | "#{_name} should be between 1 and 20, instead it is #{_}" 7 | } 8 | 9 | Options p() { 10 | val options = Options(newLinesAfterLBracket=true) 11 | return options 12 | } 13 | -------------------------------------------------------------------------------- /turin-compiler/src/test/resources/reference_to_static_field_compiled.to: -------------------------------------------------------------------------------- 1 | namespace refstat 2 | 3 | import java.nio.charset.* 4 | 5 | Charset charset() { 6 | return StandardCharsets.v#UTF_8 7 | } 8 | -------------------------------------------------------------------------------- /turin-compiler/src/test/resources/relational_operators.to: -------------------------------------------------------------------------------- 1 | namespace examples 2 | 3 | type A { 4 | boolean foo1() = 20 == 20 5 | boolean foo2() = 50 == 50 6 | boolean foo3() = 20 == 50 7 | boolean foo4() = 50 == 20 8 | boolean foo5() = 20 != 20 9 | boolean foo6() = 50 != 50 10 | boolean foo7() = 20 != 50 11 | boolean foo8() = 50 != 20 12 | boolean foo9() = 50 < 20 13 | boolean foo10() = 20 < 20 14 | boolean foo11() = 20 < 50 15 | boolean foo12() = 50 <= 20 16 | boolean foo13() = 20 <= 20 17 | boolean foo14() = 20 <= 50 18 | boolean foo15() = 50 > 20 19 | boolean foo16() = 20 > 20 20 | boolean foo17() = 20 > 50 21 | boolean foo18() = 50 >= 20 22 | boolean foo19() = 20 >= 20 23 | boolean foo20() = 20 >= 50 24 | 25 | boolean foo21(int a) = a >= 1 and a <= 20 26 | boolean foo22(int a) = a >= 1 27 | boolean foo23(int a) = a <= 20 28 | boolean foo24(int a) = a >= 1 or a <= 20 29 | } 30 | 31 | -------------------------------------------------------------------------------- /turin-compiler/src/test/resources/relations/relation_subset.to: -------------------------------------------------------------------------------- 1 | namespace relations 2 | 3 | import java.util.List 4 | 5 | type Node { 6 | } 7 | 8 | type FormalArgument extends Node { 9 | } 10 | 11 | type TypeUsage extends Node { 12 | } 13 | 14 | relation Ast { 15 | one Node parent 16 | many Node children 17 | } 18 | 19 | type Method extends Node { 20 | List[FormalArgument] params = subset of AST{parent=this}:children 21 | TypeUsage returnType = subset of AST{parent=this}:children 22 | } 23 | -------------------------------------------------------------------------------- /turin-compiler/src/test/resources/relations/relation_usage.to: -------------------------------------------------------------------------------- 1 | namespace relations 2 | 3 | import java.util.List 4 | 5 | type Node { 6 | String name 7 | } 8 | 9 | relation Ast { 10 | one Node parent 11 | many Node children 12 | } 13 | 14 | boolean foo1() { 15 | val a = Node("A") 16 | val b = Node("B") 17 | val c = Node("C") 18 | a.parent.set(b) 19 | a.parent.set(c) 20 | return a.parent.isPresent() 21 | } 22 | 23 | Node foo2() { 24 | val a = Node("A") 25 | val b = Node("B") 26 | val c = Node("C") 27 | a.parent.set(b) 28 | a.parent.set(c) 29 | return a.parent.get() 30 | } 31 | 32 | List[Node] foo3() { 33 | val a = Node("A") 34 | val b = Node("B") 35 | val c = Node("C") 36 | a.parent.set(b) 37 | a.parent.set(c) 38 | return b.children 39 | } 40 | 41 | List[Node] foo4() { 42 | val a = Node("A") 43 | val b = Node("B") 44 | val c = Node("C") 45 | a.parent.set(b) 46 | a.parent.set(c) 47 | return c.children 48 | } 49 | -------------------------------------------------------------------------------- /turin-compiler/src/test/resources/relations/simple_relation.to: -------------------------------------------------------------------------------- 1 | namespace relations 2 | 3 | import java.util.List 4 | 5 | type Node { 6 | } 7 | 8 | relation Ast { 9 | one Node parent 10 | many Node children 11 | } 12 | -------------------------------------------------------------------------------- /turin-compiler/src/test/resources/scenarios/constructor_extends1/points.to: -------------------------------------------------------------------------------- 1 | namespace points 2 | 3 | type Point { 4 | int x 5 | int y 6 | int z default 0 7 | int area = x*x + y*y + z*z 8 | } 9 | 10 | type LabelledPoint extends Point { 11 | String label 12 | } 13 | 14 | LabelledPoint foo1() = LabelledPoint(1, 2, "hi") 15 | LabelledPoint foo2() = LabelledPoint(1, 2, "hi", 3) 16 | LabelledPoint foo3() = LabelledPoint(y=2, z=3, x=1, label="hi") 17 | LabelledPoint foo4() = LabelledPoint(y=2, x=1, label="hi") 18 | -------------------------------------------------------------------------------- /turin-compiler/src/test/resources/scenarios/constructorinseparateclassdir/classdira/foo.to: -------------------------------------------------------------------------------- 1 | namespace refsrc 2 | 3 | type Abc { 4 | int a 5 | int b default 5 6 | } 7 | -------------------------------------------------------------------------------- /turin-compiler/src/test/resources/scenarios/constructorinseparateclassdir/classdirb/foo_test.to: -------------------------------------------------------------------------------- 1 | namespace refsrc 2 | 3 | Abc foo1() { 4 | return Abc(27) 5 | } 6 | 7 | Abc foo2() { 8 | return Abc(27, 28) 9 | } 10 | 11 | Abc foo3() { 12 | return Abc(b=27, a=28) 13 | } 14 | -------------------------------------------------------------------------------- /turin-compiler/src/test/resources/scenarios/overloadresolution/foo.to: -------------------------------------------------------------------------------- 1 | namespace foo 2 | 3 | int bar() = 1 4 | -------------------------------------------------------------------------------- /turin-compiler/src/test/resources/scenarios/overloadresolution/foo_test.to: -------------------------------------------------------------------------------- 1 | namespace foo 2 | 3 | import turin.test.Test 4 | 5 | @Test 6 | void fooTestSuccess() { 7 | org.junit.Assert.assertEquals(1, bar()) 8 | } 9 | -------------------------------------------------------------------------------- /turin-compiler/src/test/resources/scenarios/referencefunctionfromothersrcfile/foo.to: -------------------------------------------------------------------------------- 1 | namespace foo 2 | 3 | int bar() = 1 4 | -------------------------------------------------------------------------------- /turin-compiler/src/test/resources/scenarios/referencefunctionfromothersrcfile/foo_test.to: -------------------------------------------------------------------------------- 1 | namespace foo 2 | 3 | import turin.test.Test 4 | 5 | @Test 6 | void fooTestSuccess() { 7 | // reference to function 8 | bar() 9 | } 10 | -------------------------------------------------------------------------------- /turin-compiler/src/test/resources/scenarios/referencetoseparateclassdir/classdira/foo.to: -------------------------------------------------------------------------------- 1 | namespace refsrc 2 | 3 | type Abc { 4 | int a = 9876 5 | } 6 | -------------------------------------------------------------------------------- /turin-compiler/src/test/resources/scenarios/referencetoseparateclassdir/classdirb/foo_test.to: -------------------------------------------------------------------------------- 1 | namespace refsrc 2 | 3 | int ref() { 4 | return Abc().getA() 5 | } 6 | -------------------------------------------------------------------------------- /turin-compiler/src/test/resources/scenarios/referencetypefromothersrcfile/foo.to: -------------------------------------------------------------------------------- 1 | namespace refsrc 2 | 3 | type Abc { 4 | int a = 9876 5 | } 6 | -------------------------------------------------------------------------------- /turin-compiler/src/test/resources/scenarios/referencetypefromothersrcfile/foo_test.to: -------------------------------------------------------------------------------- 1 | namespace refsrc 2 | 3 | int ref() { 4 | return Abc().getA() 5 | } 6 | -------------------------------------------------------------------------------- /turin-compiler/src/test/resources/static_methods_invokation.to: -------------------------------------------------------------------------------- 1 | namespace manga 2 | 3 | import java.util.Collections 4 | 5 | Object myEmptyList() = Collections.emptyList() 6 | -------------------------------------------------------------------------------- /turin-compiler/src/test/resources/throw_statement.to: -------------------------------------------------------------------------------- 1 | namespace manga 2 | 3 | void parse(String path) { 4 | throw UnsupportedOperationException("To be implemented") 5 | } 6 | -------------------------------------------------------------------------------- /turin-compiler/src/test/resources/throw_statement_using_string.to: -------------------------------------------------------------------------------- 1 | namespace manga 2 | 3 | void parse(String path) { 4 | throw "To be implemented" 5 | } 6 | -------------------------------------------------------------------------------- /turin-compiler/src/test/resources/try_catch_statement.to: -------------------------------------------------------------------------------- 1 | namespace trycatch 2 | 3 | import java.io.IOException 4 | 5 | int parse(int i) { 6 | try { 7 | if i == 0 { 8 | throw IOException("foo") 9 | } elif i == 1 { 10 | throw RuntimeException("bar") 11 | } else { 12 | return i 13 | } 14 | } catch IOException e { 15 | return -1 16 | } catch RuntimeException e { 17 | return -2 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /turin-compiler/src/test/resources/type_extending.to: -------------------------------------------------------------------------------- 1 | namespace foo.bar 2 | 3 | type B { 4 | } 5 | 6 | type A extends B { 7 | } 8 | -------------------------------------------------------------------------------- /turin-compiler/src/test/resources/type_implementing.to: -------------------------------------------------------------------------------- 1 | namespace foo.bar 2 | 3 | import java.io.Serializable 4 | 5 | type A implements Serializable, Cloneable { 6 | } 7 | -------------------------------------------------------------------------------- /turin-compiler/src/test/resources/ubyte_property.to: -------------------------------------------------------------------------------- 1 | namespace basictypes 2 | 3 | type A { 4 | ubyte a 5 | } 6 | 7 | A foo1() = A(-1B) 8 | A foo2() = A(0B) 9 | A foo3() = A(1B) 10 | -------------------------------------------------------------------------------- /turin-compiler/src/test/resources/udouble_property.to: -------------------------------------------------------------------------------- 1 | namespace basictypes 2 | 3 | type A { 4 | udouble a 5 | } 6 | 7 | A foo1() = A(-1.0) 8 | A foo2() = A(0.0) 9 | A foo3() = A(1.0) 10 | -------------------------------------------------------------------------------- /turin-compiler/src/test/resources/ufloat_property.to: -------------------------------------------------------------------------------- 1 | namespace basictypes 2 | 3 | type A { 4 | ufloat a 5 | } 6 | 7 | A foo1() = A(-1.0F) 8 | A foo2() = A(0.0F) 9 | A foo3() = A(1.0F) 10 | -------------------------------------------------------------------------------- /turin-compiler/src/test/resources/uint_property.to: -------------------------------------------------------------------------------- 1 | namespace basictypes 2 | 3 | type A { 4 | uint a 5 | } 6 | 7 | A foo1() = A(-1) 8 | A foo2() = A(0) 9 | A foo3() = A(1) 10 | -------------------------------------------------------------------------------- /turin-compiler/src/test/resources/ulong_property.to: -------------------------------------------------------------------------------- 1 | namespace basictypes 2 | 3 | type A { 4 | ulong a 5 | } 6 | 7 | A foo1() = A(-1L) 8 | A foo2() = A(0L) 9 | A foo3() = A(1L) 10 | -------------------------------------------------------------------------------- /turin-compiler/src/test/resources/use_jar.to: -------------------------------------------------------------------------------- 1 | namespace foo 2 | 3 | import com.github.javaparser.ast.comments.LineComment 4 | 5 | String foo(String content) { 6 | return LineComment(content).getContent() 7 | } 8 | -------------------------------------------------------------------------------- /turin-compiler/src/test/resources/use_jar_constructor.to: -------------------------------------------------------------------------------- 1 | namespace foo 2 | 3 | import com.github.javaparser.ast.comments.* 4 | 5 | Comment foo(String content) { 6 | return LineComment(content) 7 | } 8 | -------------------------------------------------------------------------------- /turin-compiler/src/test/resources/use_jar_method.to: -------------------------------------------------------------------------------- 1 | namespace foo 2 | 3 | import com.github.javaparser.ast.comments.Comment 4 | 5 | String foo(Comment comment) { 6 | return comment.getContent() 7 | } 8 | -------------------------------------------------------------------------------- /turin-compiler/src/test/resources/use_jar_static_method.to: -------------------------------------------------------------------------------- 1 | namespace test 2 | 3 | import com.github.javaparser.JavaParser 4 | import com.github.javaparser.ast.expr.Expression 5 | 6 | Expression parse() { 7 | return JavaParser.parseExpression("1 + 2") 8 | } 9 | -------------------------------------------------------------------------------- /turin-compiler/src/test/resources/ushort_property.to: -------------------------------------------------------------------------------- 1 | namespace basictypes 2 | 3 | type A { 4 | ushort a 5 | } 6 | 7 | A foo1() = A(-1S) 8 | A foo2() = A(0S) 9 | A foo3() = A(1S) 10 | -------------------------------------------------------------------------------- /turin-parser/src/main/java/me/tomassetti/turin/parser/InternalParser.java: -------------------------------------------------------------------------------- 1 | package me.tomassetti.turin.parser; 2 | 3 | import me.tomassetti.parser.antlr.TurinLexer; 4 | import me.tomassetti.parser.antlr.TurinParser; 5 | import org.antlr.v4.runtime.*; 6 | 7 | import java.io.IOException; 8 | import java.io.InputStream; 9 | 10 | public class InternalParser { 11 | 12 | public TurinParser.TurinFileContext produceParseTree(InputStream inputStream) throws IOException { 13 | CharStream charStream = new ANTLRInputStream(inputStream); 14 | TurinLexer l = new TurinLexer(charStream); 15 | TurinParser p = new TurinParser(new CommonTokenStream(l)); 16 | p.addErrorListener(new BaseErrorListener() { 17 | @Override 18 | public void syntaxError(Recognizer recognizer, Object offendingSymbol, int line, int charPositionInLine, String msg, RecognitionException e) { 19 | throw new IllegalStateException("failed to parse at L " + line + ", C " + charPositionInLine + " due to " + msg, e); 20 | } 21 | }); 22 | TurinParser.TurinFileContext turinFileContext = p.turinFile(); 23 | if (l._mode != 0) { 24 | throw new RuntimeException("Lexical error"); 25 | } 26 | return turinFileContext; 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /turin-parser/src/test/resources/me/tomassetti/turin/args_length_different_from_one.to: -------------------------------------------------------------------------------- 1 | namespace a 2 | 3 | void foo() = args.length != 1 4 | -------------------------------------------------------------------------------- /turin-parser/src/test/resources/me/tomassetti/turin/context_definition.to: -------------------------------------------------------------------------------- 1 | namespace a 2 | 3 | context int a 4 | context String b 5 | 6 | 7 | -------------------------------------------------------------------------------- /turin-parser/src/test/resources/me/tomassetti/turin/context_scope.to: -------------------------------------------------------------------------------- 1 | namespace a 2 | 3 | program Foo(String[] args) { 4 | context (a=1, b="foo") { 5 | val c = 0 6 | } 7 | } 8 | 9 | -------------------------------------------------------------------------------- /turin-parser/src/test/resources/me/tomassetti/turin/context_usage.to: -------------------------------------------------------------------------------- 1 | namespace a 2 | 3 | program Foo(String[] args) { 4 | val zut = context.a 5 | val bar = context.b 6 | } 7 | 8 | -------------------------------------------------------------------------------- /turin-parser/src/test/resources/me/tomassetti/turin/explicit_constructor.to: -------------------------------------------------------------------------------- 1 | namespace explicit_constructors 2 | 3 | type A { 4 | 5 | String a 6 | 7 | init(int a) { 8 | this.a = Integer.toString(a) 9 | } 10 | 11 | } 12 | -------------------------------------------------------------------------------- /turin-parser/src/test/resources/me/tomassetti/turin/field_access.to: -------------------------------------------------------------------------------- 1 | namespace a 2 | 3 | void foo() = args.length 4 | -------------------------------------------------------------------------------- /turin-parser/src/test/resources/me/tomassetti/turin/field_constraint.to: -------------------------------------------------------------------------------- 1 | namespace field_constraints 2 | 3 | type Options { 4 | int a : true | "#{_name} should be between 1 and 20, instead it is #{_}" 5 | } 6 | -------------------------------------------------------------------------------- /turin-parser/src/test/resources/me/tomassetti/turin/function_definitions_block.to: -------------------------------------------------------------------------------- 1 | namespace foo 2 | 3 | int sum(int a, int b) { 4 | return a + b 5 | } 6 | -------------------------------------------------------------------------------- /turin-parser/src/test/resources/me/tomassetti/turin/function_definitions_expression.to: -------------------------------------------------------------------------------- 1 | namespace foo 2 | 3 | void toString() = "foo" 4 | -------------------------------------------------------------------------------- /turin-parser/src/test/resources/me/tomassetti/turin/imports_example.to: -------------------------------------------------------------------------------- 1 | namespace foo 2 | 3 | import java.lang.System 4 | import java.lang.System.out 5 | import java.lang.System.out.println 6 | import java.lang.System.out as out 7 | import java.lang.System.* 8 | -------------------------------------------------------------------------------- /turin-parser/src/test/resources/me/tomassetti/turin/local_var.to: -------------------------------------------------------------------------------- 1 | namespace localvar 2 | 3 | program JavaFormatter(String[] args) { 4 | val options = Options(newLinesAfterLBracket=true) 5 | } 6 | -------------------------------------------------------------------------------- /turin-parser/src/test/resources/me/tomassetti/turin/method_definitions_block.to: -------------------------------------------------------------------------------- 1 | namespace foo 2 | 3 | type MyClass { 4 | 5 | int sum(int a, int b) { 6 | return a + b 7 | } 8 | 9 | } 10 | -------------------------------------------------------------------------------- /turin-parser/src/test/resources/me/tomassetti/turin/method_definitions_expression.to: -------------------------------------------------------------------------------- 1 | namespace foo 2 | 3 | type MyClass { 4 | 5 | void toString() = "foo" 6 | 7 | } 8 | -------------------------------------------------------------------------------- /turin-parser/src/test/resources/me/tomassetti/turin/method_invokation.to: -------------------------------------------------------------------------------- 1 | namespace a 2 | 3 | void foo() = args.length() 4 | -------------------------------------------------------------------------------- /turin-parser/src/test/resources/me/tomassetti/turin/relation_subset.to: -------------------------------------------------------------------------------- 1 | namespace relations 2 | 3 | import java.util.List 4 | 5 | relation Ast { 6 | one Node parent 7 | many Node children 8 | } 9 | 10 | type Method extends Node { 11 | List[FormalArgument] params = subset of AST{parent=this}:children 12 | TypeUsage returnType = subset of AST{parent=this}:children 13 | } 14 | -------------------------------------------------------------------------------- /turin-parser/src/test/resources/me/tomassetti/turin/simple_relation.to: -------------------------------------------------------------------------------- 1 | namespace relations 2 | 3 | import java.util.List 4 | 5 | relation Ast { 6 | one Node parent 7 | many Node children 8 | } 9 | -------------------------------------------------------------------------------- /turin-parser/src/test/resources/me/tomassetti/turin/string_interp1.to: -------------------------------------------------------------------------------- 1 | namespace a 2 | 3 | void foo() = "Issue parsing #{args[0]}: #{e.getMessage()}" 4 | -------------------------------------------------------------------------------- /turin-standard-library/pom.xml: -------------------------------------------------------------------------------- 1 | 3 | 4.0.0 4 | me.tomassetti 5 | turin-standard-library 6 | jar 7 | 0.0.3-SNAPSHOT 8 | turin-standard-library 9 | https://github.com/ftomassetti/turin-programming-language 10 | 11 | 12 | me.tomassetti 13 | turin-parent 14 | 0.0.3-SNAPSHOT 15 | 16 | 17 | 18 | 19 | Apache License, Version 2.0 20 | http://www.apache.org/licenses/LICENSE-2.0.txt 21 | repo 22 | A business-friendly OSS license 23 | 24 | 25 | 26 | 27 | 28 | junit 29 | junit 30 | 4.12 31 | test 32 | 33 | 34 | org.easymock 35 | easymock 36 | 3.3.1 37 | test 38 | 39 | 40 | 41 | 42 | 43 | org.apache.maven.plugins 44 | maven-compiler-plugin 45 | 46 | UTF-8 47 | 1.8 48 | 1.8 49 | 50 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /turin-standard-library/src/main/java/turin/collections/MapBuilder.java: -------------------------------------------------------------------------------- 1 | package turin.collections; 2 | 3 | import java.util.HashMap; 4 | import java.util.Map; 5 | 6 | public class MapBuilder { 7 | 8 | private Map map; 9 | 10 | public MapBuilder(){ 11 | map = new HashMap<>(); 12 | } 13 | 14 | public MapBuilder put(K key, V value) { 15 | map.put(key, value); 16 | return this; 17 | } 18 | 19 | public Map build() { 20 | return map; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /turin-standard-library/src/main/java/turin/compilation/DefaultParam.java: -------------------------------------------------------------------------------- 1 | package turin.compilation; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | @Retention(RetentionPolicy.RUNTIME) 9 | @Target({ElementType.CONSTRUCTOR, ElementType.METHOD}) 10 | public @interface DefaultParam { 11 | String name(); 12 | String typeSignature(); 13 | int index(); 14 | } 15 | -------------------------------------------------------------------------------- /turin-standard-library/src/main/java/turin/context/Context.java: -------------------------------------------------------------------------------- 1 | package turin.context; 2 | 3 | import java.util.Optional; 4 | import java.util.Stack; 5 | 6 | public abstract class Context { 7 | 8 | private final ThreadLocal> values = 9 | new ThreadLocal>() { 10 | @Override 11 | protected Stack initialValue() { 12 | return new Stack<>(); 13 | } 14 | }; 15 | 16 | public Optional get() { 17 | Stack ctx = values.get(); 18 | if (ctx.isEmpty()) { 19 | return Optional.empty(); 20 | } else { 21 | return Optional.of(ctx.get(ctx.size() - 1)); 22 | } 23 | } 24 | 25 | public void enterContext(V value) { 26 | Stack ctx = values.get(); 27 | ctx.push(value); 28 | } 29 | 30 | public void exitContext() { 31 | Stack ctx = values.get(); 32 | ctx.pop(); 33 | } 34 | 35 | public boolean isEmpty() { 36 | Stack ctx = values.get(); 37 | return ctx.isEmpty(); 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /turin-standard-library/src/main/java/turin/relations/OneToOneRelation.java: -------------------------------------------------------------------------------- 1 | package turin.relations; 2 | 3 | 4 | import java.util.HashMap; 5 | import java.util.Map; 6 | 7 | public class OneToOneRelation implements Relation { 8 | 9 | private Map byEndpointA = new HashMap<>(); 10 | private Map byEndpointB = new HashMap<>(); 11 | 12 | @Override 13 | public void link(A endpointA, B endpointB) { 14 | if (areLinked(endpointA, endpointB)) { 15 | return; 16 | } 17 | if (byEndpointB.containsKey(endpointB)) { 18 | unlink(byEndpointB.get(endpointB), endpointB); 19 | } 20 | if (byEndpointA.containsKey(endpointA)) { 21 | unlink(byEndpointA.get(endpointA), endpointA); 22 | } 23 | byEndpointB.put(endpointB, endpointA); 24 | byEndpointA.put(endpointA, endpointB); 25 | } 26 | 27 | @Override 28 | public void unlink(Object professor, Object course) { 29 | byEndpointA.remove(professor); 30 | byEndpointB.remove(course); 31 | } 32 | 33 | @Override 34 | public boolean areLinked(Object a, Object b) { 35 | if (byEndpointB.containsKey(b)) { 36 | return byEndpointB.get(b).equals(a); 37 | } else { 38 | return false; 39 | } 40 | } 41 | 42 | public ReferenceSingleEndpoint getReferenceForB(B b) { 43 | return new ReferenceSingleEndpoint(b, byEndpointB, this); 44 | } 45 | 46 | public ReferenceSingleEndpoint getReferenceForA(A a) { 47 | return new ReferenceSingleEndpoint(a, byEndpointA, this); 48 | } 49 | 50 | } -------------------------------------------------------------------------------- /turin-standard-library/src/main/java/turin/relations/Subset.java: -------------------------------------------------------------------------------- 1 | package turin.relations; 2 | 3 | public class Subset { 4 | } 5 | -------------------------------------------------------------------------------- /turin-standard-library/src/main/java/turin/test/Test.java: -------------------------------------------------------------------------------- 1 | package turin.test; 2 | 3 | import java.lang.annotation.ElementType; 4 | import java.lang.annotation.Retention; 5 | import java.lang.annotation.RetentionPolicy; 6 | import java.lang.annotation.Target; 7 | 8 | /** 9 | * It is intended to be used on Turin functions. 10 | */ 11 | @Retention(RetentionPolicy.RUNTIME) 12 | @Target(ElementType.TYPE) 13 | public @interface Test { 14 | } 15 | -------------------------------------------------------------------------------- /turin-standard-library/src/test/java/turin/context/ContextTest.java: -------------------------------------------------------------------------------- 1 | package turin.context; 2 | 3 | import org.junit.After; 4 | import org.junit.Before; 5 | import org.junit.Test; 6 | 7 | import javax.swing.*; 8 | import java.util.HashMap; 9 | import java.util.Map; 10 | import java.util.Optional; 11 | 12 | import static org.junit.Assert.*; 13 | 14 | public class ContextTest { 15 | 16 | class MyContext extends Context { 17 | 18 | } 19 | 20 | @After 21 | public void tearDown() throws Exception { 22 | 23 | } 24 | 25 | @Before 26 | public void setUp() throws Exception { 27 | 28 | } 29 | 30 | @Test 31 | public void emptyCase() { 32 | MyContext ctx = new MyContext(); 33 | assertFalse(ctx.get().isPresent()); 34 | assertFalse(ctx.get().isPresent()); 35 | } 36 | 37 | @Test 38 | public void simpleCase() { 39 | MyContext ctx = new MyContext(); 40 | ctx.enterContext("foo"); 41 | assertEquals(Optional.of("foo"), ctx.get()); 42 | } 43 | 44 | @Test 45 | public void theMostRecentPrevails() { 46 | MyContext ctx = new MyContext(); 47 | ctx.enterContext("a"); 48 | ctx.enterContext("b"); 49 | ctx.enterContext("c"); 50 | assertEquals(Optional.of("c"), ctx.get()); 51 | } 52 | 53 | @Test 54 | public void testEnterAndExit() { 55 | MyContext ctx = new MyContext(); 56 | ctx.enterContext("foo"); 57 | ctx.exitContext(); 58 | assertEquals(Optional.empty(), ctx.get()); 59 | } 60 | 61 | @Test 62 | public void onExitThePreviousValueIsRestores() { 63 | MyContext ctx = new MyContext(); 64 | ctx.enterContext("a"); 65 | ctx.enterContext("b"); 66 | ctx.enterContext("c"); 67 | ctx.exitContext(); 68 | ctx.exitContext(); 69 | assertEquals(Optional.of("a"), ctx.get()); 70 | } 71 | 72 | } 73 | -------------------------------------------------------------------------------- /turin-standard-library/src/test/java/turin/relations/Course.java: -------------------------------------------------------------------------------- 1 | package turin.relations; 2 | 3 | public class Course { 4 | 5 | String name; 6 | int code; 7 | 8 | @Override 9 | public String toString() { 10 | return "Course{" + 11 | "name='" + name + '\'' + 12 | ", code=" + code + 13 | '}'; 14 | } 15 | 16 | public Course(int code, String name) { 17 | this.code = code; 18 | this.name = name; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /turin-standard-library/src/test/java/turin/relations/Professor.java: -------------------------------------------------------------------------------- 1 | package turin.relations; 2 | 3 | public class Professor { 4 | String name; 5 | 6 | @Override 7 | public String toString() { 8 | return "Professor{" + 9 | "name='" + name + '\'' + 10 | '}'; 11 | } 12 | 13 | public String getName() { 14 | return name; 15 | } 16 | 17 | public Professor(String name) { 18 | this.name = name; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /turin-standard-library/src/test/java/turin/relations/Teaching.java: -------------------------------------------------------------------------------- 1 | package turin.relations; 2 | 3 | public class Teaching { 4 | 5 | public static final OneToManyRelation RELATION = new OneToManyRelation(); 6 | 7 | public static Relation.ReferenceSingleEndpoint getTeacherOf(Course course){ 8 | return RELATION.getReferenceForB(course); 9 | } 10 | 11 | public static Relation.ReferenceMultipleEndpoint coursesTaughtBy(Professor professor) { 12 | return RELATION.getReferenceForA(professor); 13 | } 14 | 15 | public static Relation.ReferenceMultipleEndpoint subsetOfCoursesTaughtBy(Professor professor, Subset subset) { 16 | return RELATION.getReferenceForA(professor, subset); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /update_coverage.sh: -------------------------------------------------------------------------------- 1 | mvn clean package jacoco:report 2 | -------------------------------------------------------------------------------- /walkmod.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 23 | dev-files/eclipse-formatter.xml 24 | 25 | 26 | 27 | --------------------------------------------------------------------------------