├── .clang-format ├── .dockerignore ├── .gitignore ├── .gitmodules ├── .travis.yml ├── .travis ├── checkPerformance.sh ├── install.sh ├── run.sh └── tryCreateTag.sh ├── CMakeLists.txt ├── Dockerfile ├── Dockerfile.arch ├── LICENSE ├── Macros.cmake ├── README.md ├── SparrowImplicitLib ├── SparrowImplicitLib.spr ├── assert.spr ├── bitOper.llvm ├── bitOper.spr ├── charType.spr ├── check.spr ├── logic │ ├── lRef.spr │ ├── predicates.spr │ ├── prolog.spr │ ├── prologFrontend.spr │ ├── prologImpl │ │ ├── charRange.spr │ │ ├── codeGen.spr │ │ ├── errorReporter.spr │ │ ├── ir.spr │ │ ├── lType.spr │ │ ├── lexer.spr │ │ ├── location.spr │ │ ├── nodes.spr │ │ ├── parser.spr │ │ ├── sprCodeDump.spr │ │ └── token.spr │ └── recurse.spr ├── math.spr ├── meta │ ├── compiler.spr │ ├── compilerCore.spr │ ├── featherNodes.spr │ ├── location.spr │ ├── nodeKinds.spr │ └── sparrowNodes.spr ├── os.spr ├── par │ ├── atomic.llvm │ ├── atomic.spr │ ├── config.spr │ ├── locks.spr │ ├── parFor.spr │ ├── semaphore.spr │ ├── tasks.spr │ ├── tasksImpl │ │ ├── debug.spr │ │ ├── emptyTask.spr │ │ ├── idleCounter.spr │ │ ├── scheduler.spr │ │ ├── schedulerIf.spr │ │ ├── taskPrefix.spr │ │ ├── taskQueue.spr │ │ ├── taskSystem.spr │ │ ├── taskType.spr │ │ ├── tasksMain.spr │ │ └── workerImpl.spr │ ├── thread.spr │ └── tls.spr ├── precedenceUtils.spr ├── sprCore │ ├── basicDecls.spr │ ├── basicImpl.llvm │ ├── basicMeta.spr │ ├── consoleIO.spr │ ├── functionPtr.spr │ ├── mainDef.spr │ ├── mainImpl.spr │ ├── stdTypesImpl.llvm │ ├── streamBasic.spr │ └── stringCvt.spr ├── std │ ├── algorithms.spr │ ├── array.spr │ ├── bind.spr │ ├── bitset.spr │ ├── compilerInfo.spr.in │ ├── contiguousMemoryRange.spr │ ├── defaultHashFunction.spr │ ├── function.spr │ ├── hashTable.spr │ ├── list.spr │ ├── map.spr │ ├── newDelete.spr │ ├── optional.spr │ ├── ptr.spr │ ├── rMath.spr │ ├── ranges.spr │ ├── rawPtr.spr │ ├── scopedPtr.spr │ ├── set.spr │ ├── sharedPtr.spr │ ├── sortedMap.spr │ ├── sortedSet.spr │ ├── sortedTable.spr │ ├── staticArray.spr │ ├── string.spr │ ├── tuple.spr │ ├── typeTraits.spr │ ├── union.spr │ ├── utils.spr │ └── vector.spr ├── test.spr └── time.spr ├── build └── .gitignore ├── docs ├── Makefile ├── conf.py ├── index.rst ├── introduction.rst ├── lang │ ├── basicExpressions.rst │ ├── declarations.rst │ ├── generatedAssocFun.rst │ ├── generics.rst │ ├── modifiers.rst │ ├── modules.rst │ └── operators.rst ├── langFeatures.rst ├── make.bat ├── quickstart.rst ├── tut │ ├── beginnerIntoToSparrow.rst │ └── thesis.rst └── tutorials.rst ├── hooks └── post_checkout ├── others ├── sublime │ ├── Comments.tmPreferences │ ├── Indentation Rules.tmPreferences │ ├── Snippets │ │ ├── class.sublime-snippet │ │ ├── concept.sublime-snippet │ │ ├── datatype.sublime-snippet │ │ ├── datatype2.sublime-snippet │ │ ├── for.sublime-snippet │ │ ├── fun.sublime-snippet │ │ ├── if-else.sublime-snippet │ │ ├── if.sublime-snippet │ │ ├── import.sublime-snippet │ │ ├── package.sublime-snippet │ │ ├── return.sublime-snippet │ │ ├── while-step.sublime-snippet │ │ └── while.sublime-snippet │ ├── Sparrow.sublime-build │ ├── Sparrow.sublime-syntax │ ├── SymbolList-AddSpaces.tmPreferences │ ├── SymbolList-HideVars.tmPreferences │ └── syntax_test_Sparrow.spr └── tools │ ├── gen-tree.py │ └── get-types.py ├── src ├── Feather │ ├── Api │ │ └── Feather.h │ ├── CMakeLists.txt │ ├── Utils │ │ ├── FeatherUtils.h │ │ ├── FeatherUtils.hpp │ │ └── cppif │ │ │ ├── FeatherNodes.hpp │ │ │ └── FeatherTypes.hpp │ └── src │ │ ├── Api │ │ ├── Feather.c │ │ ├── Feather_Nodes.cpp │ │ ├── Feather_Nodes.h │ │ ├── Feather_Types.cpp │ │ └── Feather_Types.h │ │ ├── CtApiFunctions.cpp │ │ ├── CtApiFunctions.h │ │ ├── FeatherNodeCommonsCpp.h │ │ ├── FeatherNodeCommonsH.h │ │ ├── StdInc.h │ │ └── Utils │ │ ├── FeatherUtils.c │ │ ├── FeatherUtils.cpp │ │ └── cppif │ │ ├── FeatherNodes.cpp │ │ └── FeatherTypes.cpp ├── LLVMBackend │ ├── CMakeLists.txt │ ├── CtModule.cpp │ ├── CtModule.h │ ├── DataLayoutHelper.cpp │ ├── DataLayoutHelper.h │ ├── Generator.cpp │ ├── Generator.h │ ├── LLVMBackend.cpp │ ├── LLVMBackend.h │ ├── LLVMBackendMod.cpp │ ├── LLVMBackendMod.h │ ├── LLVMSourceCode.cpp │ ├── LLVMSourceCode.h │ ├── Module.cpp │ ├── Module.h │ ├── RtModule.cpp │ ├── RtModule.h │ ├── StdInc.h │ └── Tr │ │ ├── DebugInfo.cpp │ │ ├── DebugInfo.h │ │ ├── GlobalContext.h │ │ ├── Instruction.cpp │ │ ├── Instruction.h │ │ ├── LlvmBuilder.h │ │ ├── PrepareTranslate.cpp │ │ ├── PrepareTranslate.h │ │ ├── Scope.cpp │ │ ├── Scope.h │ │ ├── TrContext.cpp │ │ ├── TrContext.h │ │ ├── TrFunction.cpp │ │ ├── TrFunction.h │ │ ├── TrLocal.cpp │ │ ├── TrLocal.h │ │ ├── TrTopLevel.cpp │ │ ├── TrTopLevel.h │ │ ├── TrType.cpp │ │ └── TrType.h ├── Nest │ ├── Api │ │ ├── Backend.h │ │ ├── CompilationContext.h │ │ ├── Compiler.h │ │ ├── CompilerModule.h │ │ ├── EvalMode.h │ │ ├── Location.h │ │ ├── Modifier.h │ │ ├── Nest.h │ │ ├── Node.h │ │ ├── NodeArray.h │ │ ├── NodeKindRegistrar.h │ │ ├── NodeProperties.h │ │ ├── NodeRange.h │ │ ├── SourceCode.h │ │ ├── SourceCodeKindRegistrar.h │ │ ├── StringRef.h │ │ ├── SymTab.h │ │ ├── Type.h │ │ ├── TypeKindRegistrar.h │ │ └── TypeRef.h │ ├── CMakeLists.txt │ ├── Utils │ │ ├── Alloc.h │ │ ├── Assert.h │ │ ├── CompilerSettings.hpp │ │ ├── CompilerStats.hpp │ │ ├── DefaultStdInc.hpp │ │ ├── Diagnostic.h │ │ ├── Diagnostic.hpp │ │ ├── DiagnosticFormatter.hpp │ │ ├── Fwd.hpp │ │ ├── LocationUtils.h │ │ ├── NodeUtils.h │ │ ├── PrintTimer.hpp │ │ ├── Profiling.h │ │ ├── ProfilingFwd.h │ │ ├── PtrArray.h │ │ ├── PtrRange.h │ │ ├── Tuple.hpp │ │ └── cppif │ │ │ ├── CCLoc.hpp │ │ │ ├── Fwd.hpp │ │ │ ├── NodeHandle.hpp │ │ │ ├── NodeHelpers.hpp │ │ │ ├── NodeRange.hpp │ │ │ ├── NodeUtils.hpp │ │ │ ├── Range.hpp │ │ │ ├── SmallVector.hpp │ │ │ ├── StringRef.hpp │ │ │ ├── Type.hpp │ │ │ └── TypeWithStorage.hpp │ └── src │ │ ├── Api │ │ ├── Backend.c │ │ ├── CompilationContext.c │ │ ├── Compiler.cpp │ │ ├── Nest.c │ │ ├── Node.c │ │ ├── NodeKindRegistrar.c │ │ ├── NodeProperties.c │ │ ├── SourceCode.c │ │ ├── SourceCodeKindRegistrar.c │ │ ├── SymTab.cpp │ │ ├── Type.cpp │ │ └── TypeKindRegistrar.c │ │ ├── StdInc.hpp │ │ └── Utils │ │ ├── Alloc.c │ │ ├── ConsoleColors.hpp │ │ ├── Diagnostic.cpp │ │ ├── DiagnosticFormatter.cpp │ │ ├── LocationUtils.c │ │ ├── Profiling.cpp │ │ ├── PtrArray.c │ │ └── cppif │ │ ├── NodeHandle.cpp │ │ ├── NodeRange.cpp │ │ ├── NodeUtils.cpp │ │ ├── StringRef.cpp │ │ ├── Type.cpp │ │ └── TypeWithStorage.cpp ├── SparrowCompiler │ ├── AstDump.cpp │ ├── AstDump.h │ ├── CMakeLists.txt │ ├── Settings.cpp │ ├── Settings.h │ ├── SparrowCompiler.cpp │ ├── StdInc.h │ └── VersionInfo.h.in └── SparrowFrontend │ ├── CMakeLists.txt │ ├── CtApiFunctions.cpp │ ├── CtApiFunctions.h │ ├── Grammar │ ├── Parser.cpp │ ├── Parser.h │ ├── bufferedCharSource.spr │ ├── ext.spr │ ├── fileCharSource.spr │ ├── layoutDecoder.spr │ ├── node.spr │ ├── parser.spr │ ├── parserDefs.spr │ ├── parserIf.ll │ ├── parserIf.spr │ ├── rangeWithLookahead.spr │ ├── scanner.spr │ ├── stringCharSource.spr │ └── token.spr │ ├── Helpers │ ├── CommonCode.cpp │ ├── CommonCode.h │ ├── Ct.cpp │ ├── Ct.h │ ├── DeclsHelpers.cpp │ ├── DeclsHelpers.h │ ├── Generics.cpp │ ├── Generics.h │ ├── Impl │ │ ├── Intrinsics.cpp │ │ └── Intrinsics.h │ ├── QualifiedId.cpp │ ├── QualifiedId.h │ ├── SprTypeTraits.cpp │ ├── SprTypeTraits.h │ ├── StdDef.cpp │ └── StdDef.h │ ├── IntMods.cpp │ ├── IntMods.h │ ├── Mods.cpp │ ├── Mods.h │ ├── NodeCommonsCpp.h │ ├── NodeCommonsH.h │ ├── Nodes │ ├── AccessType.h │ ├── Builder.cpp │ ├── Builder.h │ ├── Decl.cpp │ ├── Decl.hpp │ ├── Exp.cpp │ ├── Exp.hpp │ ├── Generics.cpp │ ├── Generics.hpp │ ├── Module.cpp │ ├── Module.hpp │ ├── SparrowNodes.cpp │ ├── SparrowNodes.h │ ├── SprProperties.cpp │ ├── SprProperties.h │ ├── Stmt.cpp │ └── Stmt.hpp │ ├── Services │ ├── Callable │ │ ├── Callable.cpp │ │ ├── Callable.h │ │ ├── CallableHelpers.cpp │ │ ├── CallableHelpers.h │ │ ├── CallableServiceImpl.cpp │ │ ├── CallableServiceImpl.h │ │ ├── Callables.cpp │ │ ├── Callables.h │ │ ├── ConceptCallable.cpp │ │ ├── ConceptCallable.h │ │ ├── FunctionCallable.cpp │ │ ├── FunctionCallable.h │ │ ├── GenericDatatypeCallable.cpp │ │ ├── GenericDatatypeCallable.h │ │ ├── GenericFunctionCallable.cpp │ │ ├── GenericFunctionCallable.h │ │ ├── GenericPackageCallable.cpp │ │ └── GenericPackageCallable.h │ ├── Concepts │ │ ├── ConceptsServiceImpl.cpp │ │ └── ConceptsServiceImpl.h │ ├── Convert │ │ ├── ConversionResult.cpp │ │ ├── ConversionResult.h │ │ ├── ConvertServiceImpl.cpp │ │ └── ConvertServiceImpl.h │ ├── ICallableService.h │ ├── IConceptsService.h │ ├── IConvertService.h │ ├── IOverloadService.h │ └── Overload │ │ ├── OverloadServiceImpl.cpp │ │ └── OverloadServiceImpl.h │ ├── SparrowFrontend.cpp │ ├── SparrowFrontend.h │ ├── SparrowFrontendTypes.cpp │ ├── SparrowFrontendTypes.hpp │ ├── SparrowSourceCode.cpp │ ├── SparrowSourceCode.h │ ├── SprDebug.cpp │ ├── SprDebug.h │ ├── StdInc.h │ ├── UserDefinedSourceCode.cpp │ └── UserDefinedSourceCode.h ├── tests ├── Basic │ ├── Auto.spr │ ├── Basic.spr │ ├── CompDefines.spr │ ├── Compound.spr │ ├── Concepts.spr │ ├── CtFactorial.spr │ ├── CtFun.spr │ ├── CtIf.spr │ ├── CtToRt.spr │ ├── CtToRtComplex.spr │ ├── CtToRtErr.spr │ ├── CtorDtor.spr │ ├── DependentTypes.spr │ ├── ExternalCtor.spr │ ├── Functor.spr │ ├── GeneratedCtorDtor.spr │ ├── Generics.spr │ ├── IfClause.spr │ ├── ImplicitFunCall.spr │ ├── LLVMCode.llvm │ ├── ObjectCopy.spr │ ├── ObjectCopyRVO.spr │ ├── SameName.spr │ ├── SparrowImplicitLib.spr │ ├── StaticCtorDtor.spr │ ├── Stmt.spr │ ├── String.spr │ ├── This.spr │ ├── TypeVar.spr │ ├── Using.spr │ ├── ValueToRef.spr │ ├── datatype │ │ ├── autoBitcopiable.spr │ │ ├── bitcopiable.spr │ │ ├── datatypeCat.spr │ │ ├── funApi.spr │ │ ├── generic.spr │ │ ├── initCtor.spr │ │ ├── interaction.spr │ │ ├── queryBitcopiable.spr │ │ ├── storage.spr │ │ └── syntax.spr │ ├── exp │ │ └── dotOper.spr │ ├── fun │ │ ├── callCtorDtor.spr │ │ ├── callOperator.spr │ │ ├── defaultParam.spr │ │ ├── funExp.spr │ │ ├── funSyntax.spr │ │ ├── operators.spr │ │ ├── overloadBasic.spr │ │ └── overloadCat.spr │ ├── types │ │ ├── ptrOfCat.spr │ │ ├── returnsTemp.spr │ │ ├── temp.spr │ │ └── typeTraits.spr │ └── vars │ │ ├── typeCatFieldsErr.spr │ │ └── typeCatVarsErr.spr ├── Basic2 │ ├── Axioms.spr │ ├── ConceptOfGeneric.spr │ ├── ConceptSpecialization.spr │ ├── Conditional.spr │ ├── CtFor.spr │ ├── CtRtCalls.spr │ ├── CtRtParam.spr │ ├── CtWhile.spr │ ├── CustomOperators.spr │ ├── For.spr │ ├── FunPtrTest.spr │ ├── GenericFunRef.spr │ ├── GenericPackage.spr │ ├── InstSpeed.spr │ ├── Lambda.spr │ ├── LogicalAndOr.spr │ ├── Precedence.spr │ ├── Regular.spr │ ├── Swappable.spr │ └── TypeTraits.spr ├── BenchmarkGame │ ├── fannkuchredux.spr │ ├── fasta.spr │ ├── fastaredux.spr │ ├── meteor.spr │ └── nbody.spr ├── Bugs │ ├── CastOnAssignment.spr │ ├── GenericWithCtConcept.spr │ ├── NullConstant.spr │ ├── Overload.spr │ ├── ParenInGeneric.spr │ ├── SpecializationOnCt.spr │ ├── StaticGlobal.spr │ ├── TwiceFor.spr │ ├── VectorOfCtClass.spr │ ├── WhileVarCond.spr │ └── test.spr ├── CompilerApi │ ├── ApiSmokeTest.spr │ ├── AstFactorial.spr │ └── Diagnostic.spr ├── Examples │ ├── MinPerfHash.spr │ ├── NQueens-solAtRt.spr │ ├── NQueens.spr │ ├── Power.spr │ ├── Regex.spr │ ├── Speak.spr │ ├── llvm-compile │ ├── others │ │ ├── mph │ │ │ ├── Makefile │ │ │ └── sparrow_cmp_test.cpp │ │ └── regex │ │ │ ├── Makefile │ │ │ ├── dfa0.c │ │ │ ├── dfa1.c │ │ │ └── nfa.c │ ├── queen-art.txt │ └── words-full ├── Frontend │ ├── Identifiers.spr │ ├── Numbers.spr │ ├── Operators.spr │ ├── PrefixPostfix.spr │ ├── Smoke.spr │ ├── StringAndDsl.spr │ └── parserTest.spr ├── Imports │ ├── HeaderA.spr │ ├── HeaderB.spr │ ├── HeaderC.spr │ ├── HeaderD.spr │ ├── ImportComplex.spr │ ├── ImportComplex2.spr │ ├── ImportDirect.spr │ ├── ImportInTheMiddle.spr │ ├── ImportRelativeFile.spr │ ├── ImportTwice.spr │ └── SelectiveImport.spr ├── Logic │ ├── Antiquotation.spr │ ├── FibOptTest.spr │ ├── FibProlog.spr │ ├── FibPrologErr.spr │ ├── FibTest.spr │ ├── Fibonacci.pl │ ├── FibonacciErr.pl │ ├── ImportProlog.spr │ ├── LogicTest.spr │ ├── Parents.spr │ ├── PrologErr1.spr │ ├── PrologErr2.spr │ ├── PrologErr3.spr │ ├── PrologParserTest.spr │ ├── Solar.pl │ ├── Solar.spr │ └── test │ │ ├── cpp │ │ └── Fib.cpp │ │ ├── do_test.pl │ │ └── results2.csv ├── Par │ ├── AtomicTest.spr │ ├── LocksTest.spr │ ├── ParForTest.spr │ ├── SemaphoreTest.spr │ ├── TaskTest.spr │ ├── ThreadTest.spr │ └── TlsTest.spr ├── PerfTests │ ├── FibRanges │ │ ├── Makefile │ │ ├── args.in │ │ ├── fib_op.c │ │ ├── fib_op.cpp │ │ ├── fib_op.spr │ │ ├── fib_op_base.spr │ │ └── programs.in │ ├── ForPerf │ │ ├── Makefile │ │ ├── args.in │ │ ├── for.c │ │ ├── for.py │ │ ├── for_post.cpp │ │ ├── for_pre.cpp │ │ ├── for_ranges.cpp │ │ ├── programs.in │ │ ├── spr_for.spr │ │ ├── spr_while.spr │ │ └── while.cpp │ ├── GoogleBench │ │ ├── .gitignore │ │ ├── LoopTesterApp.spr │ │ ├── Makefile │ │ ├── args.in │ │ └── programs.in │ ├── Hash │ │ ├── TestHashPerf.spr │ │ └── cpp │ │ │ ├── Makefile │ │ │ └── TestHashPerfCpp.cpp │ └── LazyRanges │ │ ├── Makefile │ │ ├── args.in │ │ ├── lazy_ranges.c │ │ ├── lazy_ranges.cpp │ │ ├── lazy_ranges.spr │ │ ├── lazy_ranges_base.spr │ │ └── programs.in ├── Simple │ ├── Ackermann.spr │ ├── Factorization.spr │ ├── Fibonacci.spr │ ├── GCD.spr │ ├── Primality.spr │ └── SecantMethod.spr ├── StdLib │ ├── AlgorithmsTest1.spr │ ├── AlgorithmsTest2.spr │ ├── AlgorithmsTest3.spr │ ├── AlgorithmsTest4.spr │ ├── ArrayTest.spr │ ├── AssertTest.spr │ ├── CheckTest.spr │ ├── ContiguousMemoryRangeTest.spr │ ├── FunTest.spr │ ├── HashMapTest.spr │ ├── HashSetTest.spr │ ├── ListTest.spr │ ├── PtrTest.spr │ ├── RangesTest.spr │ ├── SortedMapTest.spr │ ├── SortedSetTest.spr │ ├── StaticArrayTest.spr │ ├── StringOperators.spr │ ├── TupleTest.spr │ ├── UnionTest.spr │ ├── VectorCtTest.spr │ └── VectorTest.spr ├── perf-test.py ├── test.py └── tests.in ├── tools ├── checks │ ├── moduleName.spr │ └── returnStmt.spr ├── formatAll.py ├── formatDetails │ ├── astNodes.spr │ ├── consoleErrorReporter.spr │ ├── fileCharSourceKeepContent.spr │ ├── nodeKinds.spr │ ├── sourceData.spr │ ├── tokenData.spr │ └── tokenDataSource.spr ├── formatTool.spr └── transforms │ ├── defaultFormat.spr │ ├── emptyTransform.spr │ ├── refToMut.spr │ ├── removeEolSemicolons.spr │ ├── removeExtraSpaces.spr │ ├── useLayout.spr │ └── utils.spr └── unittests ├── CMakeLists.txt ├── Common ├── BackendMock.cpp ├── BackendMock.hpp ├── FeatherNodeFactory.cpp ├── FeatherNodeFactory.hpp ├── GeneralFixture.cpp ├── GeneralFixture.hpp ├── LocationGen.hpp ├── RcBasic.hpp ├── TypeFactory.cpp └── TypeFactory.hpp ├── DetailConsoleReporter.cpp ├── Feather ├── TestFeatherNodes.cpp └── TestTypes.cpp ├── Nest ├── MockNode.cpp ├── MockNode.hpp ├── MockType.cpp ├── MockType.hpp ├── TestNode.cpp └── TestType.cpp ├── SparrowFrontend ├── SprCommon │ ├── ConceptsServiceMock.cpp │ ├── ConceptsServiceMock.hpp │ ├── GenCallableDecl.cpp │ ├── GenCallableDecl.hpp │ ├── GenGenericParams.cpp │ ├── GenGenericParams.hpp │ ├── GenValueForType.cpp │ ├── GenValueForType.hpp │ ├── OverloadServiceMock.cpp │ ├── OverloadServiceMock.hpp │ ├── SampleTypes.cpp │ ├── SampleTypes.hpp │ └── Utils.hpp ├── TestCallable.cpp ├── TestConvert.cpp ├── TestDecls.cpp ├── TestGenerics.cpp └── metatests │ ├── TestGenCallableDecl.cpp │ ├── TestGenGenericParams.cpp │ └── TestGenValueForType.cpp ├── StdInc.h └── UnitTestsMain.cpp /.clang-format: -------------------------------------------------------------------------------- 1 | --- 2 | # We'll use defaults from the LLVM style, but with 4 columns indentation. 3 | BasedOnStyle: LLVM 4 | IndentWidth: 4 5 | ColumnLimit: 100 6 | ContinuationIndentWidth: 8 7 | --- 8 | Language: Cpp 9 | SortIncludes: false 10 | # Force pointers to the type for C++. 11 | DerivePointerAlignment: false 12 | PointerAlignment: Left 13 | AlignAfterOpenBracket: DontAlign 14 | BreakConstructorInitializersBeforeComma: true 15 | ReflowComments: true 16 | AccessModifierOffset: -4 -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | .travis 2 | build 3 | docs 4 | others 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.out 3 | *.exe 4 | *.one.llvm 5 | *.opt.llvm 6 | *.ct.llvm 7 | *.bc 8 | callgrind.out.* 9 | *-alt.ll 10 | *-alt.opt.ll 11 | .DS_Store 12 | .out 13 | out 14 | tests/Examples/others/nqueens 15 | tests/GoogleBench/orig 16 | tests/BenchmarkGame/others 17 | tests/*/*.json 18 | tests/*/*.json.dot 19 | tests/*/*.json.pdf 20 | SparrowImplicitLib/std/compilerInfo.spr 21 | src/SparrowCompiler/VersionInfo.h 22 | *.sublime-project 23 | *.sublime-workspace 24 | docs/_build 25 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "externals/rapidcheck"] 2 | path = externals/rapidcheck 3 | url = https://github.com/emil-e/rapidcheck.git 4 | branch = master 5 | [submodule "externals/tracy"] 6 | path = externals/tracy 7 | url = https://lucteo@bitbucket.org/wolfpld/tracy.git 8 | branch = master 9 | -------------------------------------------------------------------------------- /.travis/install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | set -x 5 | 6 | echo "Travis OS name: $TRAVIS_OS_NAME" 7 | echo "Travis branch: $TRAVIS_BRANCH" 8 | echo "Travis tag: $TRAVIS_TAG" 9 | echo "LANG=$LANG" 10 | echo "LC_ALL=$LC_ALL" 11 | 12 | if [ $TRAVIS_OS_NAME == osx ]; then 13 | # brew update 14 | # brew upgrade boost 15 | brew install llvm@7 16 | fi 17 | -------------------------------------------------------------------------------- /.travis/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | set -e 4 | set -x 5 | 6 | CFG_PARAMS= 7 | 8 | if [ $TRAVIS_OS_NAME == osx ]; then 9 | CFG_PARAMS="-DLLVM_DIR=/usr/local/opt/llvm@7/lib/cmake/llvm" 10 | fi 11 | 12 | if [ $TRAVIS_OS_NAME == linux ]; then 13 | export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/lib/x86_64-linux-gnu:/usr/lib/llvm-5.0/lib/ 14 | fi 15 | 16 | cd build 17 | cmake .. $CFG_PARAMS 18 | make 19 | sudo make install 20 | 21 | echo "---------- Unit testing ----------" 22 | 23 | bin/SparrowUnitTests 24 | 25 | echo "---------- Testing ----------" 26 | 27 | cd ../tests 28 | 29 | python test.py StdLib/RangesTest.spr --returnError 30 | python test.py --returnError 31 | -------------------------------------------------------------------------------- /.travis/tryCreateTag.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | export MAJOR_VER=0 4 | export MINOR_VER=10 5 | 6 | echo "TRAVIS_BRANCH: $TRAVIS_BRANCH" 7 | echo "TRAVIS_TAG: $TRAVIS_TAG" 8 | echo "TRAVIS_COMMIT: $TRAVIS_COMMIT" 9 | 10 | # Create a tag only for master builds (excluding tag-triggered builds) 11 | if [ "$MAIN_BUILD" == "1" ] && [ "$TRAVIS_BRANCH" == "master" ] && [ -z "$TRAVIS_TAG" ]; then 12 | export GIT_BUILDNUM=$(git rev-list --first-parent --count $TRAVIS_COMMIT) 13 | export GIT_TAG=v$MAJOR_VER.$MINOR_VER.$GIT_BUILDNUM 14 | echo "Applying tag $GIT_TAG" 15 | git tag $GIT_TAG -a -m "Release of version $GIT_TAG" 16 | 17 | API_JSON=$(printf '{"tag_name": "%s","target_commitish": "master","name": "%s","body": "Release of version %s","draft": false,"prerelease": false}' $GIT_TAG $GIT_TAG $GIT_TAG) 18 | curl -s -o /dev/null --data "$API_JSON" https://api.github.com/repos/Sparrow-lang/sparrow/releases?access_token=$GITHUBKEY 19 | # This can fail 20 | # Please note that we have multiple jobs that may attempt to create the same tag 21 | fi 22 | 23 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM sparrowlang/sparrowdeps 2 | 3 | # Copy the Sparrow source files 4 | RUN mkdir /sparrow 5 | RUN mkdir /sparrow/src 6 | RUN mkdir /sparrow/externals 7 | RUN mkdir /sparrow/unittests 8 | RUN mkdir /sparrow/SparrowImplicitLib 9 | COPY src /sparrow/src 10 | COPY externals /sparrow/externals 11 | COPY unittests /sparrow/unittests 12 | COPY SparrowImplicitLib /sparrow/SparrowImplicitLib 13 | COPY CMakeLists.txt /sparrow/ 14 | COPY Macros.cmake /sparrow/ 15 | COPY LICENSE /sparrow/ 16 | COPY .git /sparrow/.git 17 | 18 | # Copy the test files 19 | RUN mkdir /sparrow_tests 20 | COPY tests /sparrow_tests 21 | 22 | # Do the build 23 | WORKDIR /sparrow 24 | RUN mkdir /sparrow/build 25 | WORKDIR /sparrow/build 26 | RUN cmake .. 27 | # Just make sure we don't copy this file 28 | RUN rm -f ../src/SparrowFrontend/Grammar/parserIf.o 29 | RUN cmake --build . -- -j4 30 | RUN cmake --build . -- install 31 | 32 | # Run the unit tests 33 | WORKDIR /sparrow/build/bin 34 | RUN ./SparrowUnitTests 35 | 36 | # Ensure the newly installed libraries can be found 37 | RUN ldconfig 38 | 39 | # Test the build 40 | WORKDIR /sparrow_tests 41 | RUN python test.py 42 | 43 | # Remove temporary files 44 | RUN rm -rf /sparrow 45 | -------------------------------------------------------------------------------- /Dockerfile.arch: -------------------------------------------------------------------------------- 1 | FROM archlinux/base 2 | 3 | # Install needed packages 4 | RUN pacman -Syu --noconfirm llvm clang lld 5 | RUN pacman -Syu --noconfirm boost 6 | RUN pacman -Syu --noconfirm make cmake 7 | RUN pacman -Syu --noconfirm grep python2 8 | 9 | # Copy the Sparrow source files 10 | RUN mkdir /sparrow 11 | RUN mkdir /sparrow/src 12 | RUN mkdir /sparrow/externals 13 | RUN mkdir /sparrow/unittests 14 | RUN mkdir /sparrow/SparrowImplicitLib 15 | COPY src /sparrow/src 16 | COPY externals /sparrow/externals 17 | COPY unittests /sparrow/unittests 18 | COPY SparrowImplicitLib /sparrow/SparrowImplicitLib 19 | COPY CMakeLists.txt /sparrow/ 20 | COPY Macros.cmake /sparrow/ 21 | COPY LICENSE /sparrow/ 22 | COPY .git /sparrow/.git 23 | 24 | # Copy the test files 25 | RUN mkdir /sparrow_tests 26 | COPY tests /sparrow_tests 27 | 28 | # Do the build 29 | WORKDIR /sparrow 30 | RUN mkdir /sparrow/build 31 | WORKDIR /sparrow/build 32 | # RUN CC=clang CXX=clang++ cmake .. 33 | RUN cmake .. 34 | RUN cmake --build . -- -j4 35 | RUN cmake --build . -- install 36 | 37 | # Run the unit tests 38 | WORKDIR /sparrow/build/bin 39 | RUN ./SparrowUnitTests 40 | 41 | # Ensure the newly installed libraries can be found 42 | RUN ldconfig 43 | 44 | # Test the build 45 | WORKDIR /sparrow_tests 46 | RUN python2 test.py 47 | 48 | # Remove temporary files 49 | RUN rm -rf /sparrow 50 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015, Lucian Radu Teodorescu 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /SparrowImplicitLib/SparrowImplicitLib.spr: -------------------------------------------------------------------------------- 1 | import "sprCore/stdTypesImpl.llvm" 2 | import "sprCore/basicImpl.llvm" 3 | import "bitOper.llvm" 4 | 5 | [public] 6 | import sprCore.basicDecls 7 | 8 | import sprCore.functionPtr 9 | 10 | import sprCore.streamBasic 11 | import sprCore.consoleIO 12 | import sprCore.mainDef 13 | import sprCore.stringCvt 14 | import sprCore.basicMeta 15 | -------------------------------------------------------------------------------- /SparrowImplicitLib/charType.spr: -------------------------------------------------------------------------------- 1 | fun isAlnum(c: Char) = 0 != _Impl.isalnum(Int(c)) 2 | fun isAlpha(c: Char) = 0 != _Impl.isalpha(Int(c)) 3 | fun isBlank(c: Char) = 0 != _Impl.isblank(Int(c)) 4 | fun isCntrl(c: Char) = 0 != _Impl.iscntrl(Int(c)) 5 | fun isDigit(c: Char) = 0 != _Impl.isdigit(Int(c)) 6 | fun isGraph(c: Char) = 0 != _Impl.isgraph(Int(c)) 7 | fun isLower(c: Char) = 0 != _Impl.islower(Int(c)) 8 | fun isPrint(c: Char) = 0 != _Impl.isprint(Int(c)) 9 | fun isPunct(c: Char) = 0 != _Impl.ispunct(Int(c)) 10 | fun isSpace(c: Char) = 0 != _Impl.isspace(Int(c)) 11 | fun isUpper(c: Char) = 0 != _Impl.isupper(Int(c)) 12 | fun isXdigit(c: Char) = 0 != _Impl.isxdigit(Int(c)) 13 | 14 | package _Impl 15 | [native("isalnum")] fun isalnum(c: Int): Int 16 | [native("isalpha")] fun isalpha(c: Int): Int 17 | [native("isblank")] fun isblank(c: Int): Int 18 | [native("iscntrl")] fun iscntrl(c: Int): Int 19 | [native("isdigit")] fun isdigit(c: Int): Int 20 | [native("isgraph")] fun isgraph(c: Int): Int 21 | [native("islower")] fun islower(c: Int): Int 22 | [native("isprint")] fun isprint(c: Int): Int 23 | [native("ispunct")] fun ispunct(c: Int): Int 24 | [native("isspace")] fun isspace(c: Int): Int 25 | [native("isupper")] fun isupper(c: Int): Int 26 | [native("isxdigit")] fun isxdigit(c: Int): Int 27 | -------------------------------------------------------------------------------- /SparrowImplicitLib/logic/prologFrontend.spr: -------------------------------------------------------------------------------- 1 | import prolog 2 | import meta.compiler 3 | 4 | [ct] let _dummy1 = registerFrontendFun(".pl", "logic/prolog.spr:handlePrologCode") 5 | -------------------------------------------------------------------------------- /SparrowImplicitLib/logic/prologImpl/charRange.spr: -------------------------------------------------------------------------------- 1 | concept CharRange(x: Range) if -@(x.RetType) == Char 2 | -------------------------------------------------------------------------------- /SparrowImplicitLib/logic/prologImpl/location.spr: -------------------------------------------------------------------------------- 1 | import metaloc = meta.location 2 | 3 | // Use the same location infrastructure as the one we use in the compiler 4 | using LLocation = metaloc.Location 5 | using Location = metaloc.Location 6 | 7 | -------------------------------------------------------------------------------- /SparrowImplicitLib/meta/compiler.spr: -------------------------------------------------------------------------------- 1 | [public] import compilerCore 2 | 3 | [ct] 4 | [native("$meta.Compiler.registerFrontendFun")] 5 | fun registerFrontendFun(ext, funName: StringRef): Bool 6 | [native("$meta.Compiler.parseSprExpression")] 7 | fun parseSprExpression(loc: Location const, exp: StringRef): AstNode 8 | -------------------------------------------------------------------------------- /SparrowImplicitLib/par/config.spr: -------------------------------------------------------------------------------- 1 | module par.config 2 | 3 | import std.ptr 4 | 5 | [bitcopiable] 6 | datatype NativeThreadHandle = Int8 Ptr // Opaque type 7 | 8 | fun >>(h: NativeThreadHandle, os: !OutStream) 9 | if ( h.impl.isSet ) 10 | os << UntypedPtr(h.impl.get) 11 | else 12 | os << "null" 13 | 14 | using InvalidThreadHandle = NativeThreadHandle() 15 | 16 | //! Get the number of available logical CPU cores for our process 17 | //! This dictates how much parallelism we have to be exploit 18 | fun getAvailableCoresNum(): Int 19 | let maxProcs: Int = _Impl.sysconf(_Impl._SC_NPROCESSORS_ONLN) 20 | return ife(maxProcs<1, 1, maxProcs) 21 | // TODO: also consider process affinity 22 | 23 | package _Impl 24 | using _SC_NPROCESSORS_ONLN = 58 25 | 26 | [native("sysconf")] fun sysconf(name: Int): Int64 27 | 28 | -------------------------------------------------------------------------------- /SparrowImplicitLib/par/tasksImpl/debug.spr: -------------------------------------------------------------------------------- 1 | module par.tasksImpl.debug 2 | 3 | import par.locks 4 | import std.string 5 | 6 | using traceCalls = false 7 | 8 | using TraceLockType = Mutex 9 | 10 | var traceMutex: TraceLockType 11 | 12 | //! Helper class that does the trace while holding a mutex 13 | //! Prevents the output to be messed up 14 | datatype Tracer 15 | 16 | [protected] 17 | fun ctor(this: !Tracer) 18 | [ct] if traceCalls 19 | traceMutex lock 20 | 21 | fun ctor(this: !Tracer, workerId: Int, depth: Int) 22 | [ct] if traceCalls 23 | traceMutex lock 24 | cout << workerId << ": " << Depth(depth) 25 | 26 | fun dtor(this: !Tracer) 27 | [ct] if traceCalls 28 | traceMutex unlock 29 | 30 | fun <<<(this: !Tracer, x: AnyType) 31 | [ct] if traceCalls 32 | cout << x 33 | 34 | [initCtor] 35 | datatype Depth 36 | depth: Int 37 | 38 | fun >> (d: Depth, os: !OutStream) 39 | if d.depth > 0 40 | os << String(d.depth*2, ' '.char) 41 | 42 | -------------------------------------------------------------------------------- /SparrowImplicitLib/par/tasksImpl/emptyTask.spr: -------------------------------------------------------------------------------- 1 | module par.tasksImpl.emptyTask 2 | 3 | import taskPrefix(TaskPrefix) 4 | import std.string 5 | 6 | //! An empty task; can be used for synchronization 7 | datatype EmptyTask 8 | prefix: TaskPrefix 9 | 10 | fun execute(task: !EmptyTask) {} 11 | 12 | fun >>(t: EmptyTask, os: !OutStream) 13 | os << "EmptyTask" 14 | 15 | fun description(task: !EmptyTask): String = "EmptyTask" 16 | -------------------------------------------------------------------------------- /SparrowImplicitLib/par/tasksImpl/idleCounter.spr: -------------------------------------------------------------------------------- 1 | module par.tasksImpl.idleCounter 2 | 3 | import par.atomic 4 | 5 | //! Class used to keep count of the number of threads that go idle 6 | datatype IdleCounter 7 | cnt: Int Atomic 8 | 9 | //! Called by a worker thread that just decided to go IDLE 10 | fun goIdle(this: !IdleCounter) 11 | this.cnt++ 12 | //! Called by a worker thread who just got up from IDLE state 13 | fun wakeUp(this: !IdleCounter) 14 | this.cnt-- 15 | 16 | //! Check if we have some workers that are in the IDLE state 17 | fun hasIdle(this: !IdleCounter) = (this.cnt load) > 0 18 | //! Returns the number of workers that are in the IDLE state 19 | fun numIdleWorkers(this: !IdleCounter) = this.cnt load 20 | -------------------------------------------------------------------------------- /SparrowImplicitLib/par/tasksImpl/schedulerIf.spr: -------------------------------------------------------------------------------- 1 | module par.tasksImpl.schedulerIf.schedulerif 2 | 3 | import taskPrefix(TaskPrefix, TaskPtr) 4 | import sched = scheduler(schedSpawn, schedWaitForAll, schedSpawnRootAndWait, schedWaitForAll, schedEnqueue) 5 | import worker = workerImpl(localWorker) 6 | import std.ptr 7 | 8 | fun spawn(task: !TaskPrefix) 9 | sched.schedSpawn(TaskPtr(task mutToPtr)) 10 | fun spawnAndWaitForAll(curTask, child: !TaskPrefix) 11 | sched.schedWaitForAll(TaskPtr(curTask mutToPtr), TaskPtr(child mutToPtr)) 12 | fun spawnRootAndWait(root: !TaskPrefix) 13 | sched.schedSpawnRootAndWait(TaskPtr(root mutToPtr)) 14 | fun waitForAll(curTask: !TaskPrefix) 15 | sched.schedWaitForAll(TaskPtr(curTask mutToPtr), TaskPtr()) 16 | fun enqueue(task: !TaskPrefix) 17 | sched.schedEnqueue(TaskPtr(task mutToPtr)) 18 | 19 | fun localWorker(): UntypedPtr = UntypedPtr(worker.localWorker().get()) 20 | -------------------------------------------------------------------------------- /SparrowImplicitLib/par/tasksImpl/taskType.spr: -------------------------------------------------------------------------------- 1 | module par.tasksImpl.taskType 2 | 3 | [public] import taskPrefix(TaskPrefix) 4 | 5 | //! A concept describing a task that can be spawned 6 | //! 7 | //! A task must have two things: 8 | //! - an 'execute' method (that returns nothing) 9 | //! - a way of obtaining the task prefix from it 10 | //! - either as an 'prefix' method 11 | //! - or as a 'prefix' field <-- this is the easiest 12 | concept TaskType(x) \ 13 | if isValid(x execute) \ 14 | && ( isValidAndTrue(typeOf(x prefix) == @TaskPrefix) \ 15 | || isValidAndTrue(typeOf(x.prefix) == TaskPrefix) ) 16 | 17 | fun getPrefix(t: !TaskType): @TaskPrefix = t prefix if isValid(t prefix) 18 | fun getPrefix(t: !TaskType): @TaskPrefix = t.prefix mutToPtr if isValid(t.prefix) && !isValid(t prefix) 19 | 20 | -------------------------------------------------------------------------------- /SparrowImplicitLib/precedenceUtils.spr: -------------------------------------------------------------------------------- 1 | import meta.featherNodes, meta.sparrowNodes 2 | 3 | [ct, macro] 4 | fun setOperPrecedence(oper, value: CompilerAstNode): CompilerAstNode 5 | let loc = oper location 6 | let loc2 = value location 7 | let operName = astEval(oper) 8 | let precValue: Int = astEval(value) 9 | return mkSprUsing(loc, "oper_precedence_" + operName, mkIntLiteral(loc2, precValue)) 10 | 11 | fun getOperPrecedence(oper: CompilerAstNode): CompilerAstNode 12 | let loc = oper location 13 | let operName = astEval(oper) 14 | let args = mkNodeList(loc) 15 | addToNodeList(args, mkIdentifier(loc, "oper_precedence_" + operName)) 16 | addToNodeList(args, mkIdentifier(loc, "oper_precedence_default")) 17 | return mkFunApplication(loc, mkIdentifier(loc, "valueIfValid"), args) 18 | 19 | fun setOperRightAssociativity(oper: CompilerAstNode): CompilerAstNode 20 | let loc = oper location 21 | let operName = astEval(oper) 22 | return mkSprUsing(loc, "oper_assoc_" + operName, mkIntLiteral(loc, -1)) 23 | 24 | -------------------------------------------------------------------------------- /SparrowImplicitLib/sprCore/basicMeta.spr: -------------------------------------------------------------------------------- 1 | import basicDecls(UntypedPtr, Int8, StringRef, Null, pre_@) 2 | 3 | [ct] 4 | /// The type used to represent a compiler AST node 5 | [bitcopiable] 6 | datatype CompilerAstNode = @Int8 7 | 8 | /// Taking an AST node, this will evaluate the node and produce the corresponding code 9 | /// Opposite of astLift 10 | [native("$meta.astEval")] 11 | fun astEval(node: CompilerAstNode): CompilerAstNode 12 | 13 | /// Given any Sparrow node as parameter, this will transform it into an AST node 14 | /// Opposite of astEval 15 | [native("$meta.astLift")] 16 | fun astLift(node: CompilerAstNode): CompilerAstNode 17 | -------------------------------------------------------------------------------- /SparrowImplicitLib/sprCore/consoleIO.spr: -------------------------------------------------------------------------------- 1 | import basicDecls(Number, Char, Bool, StringRef, Int8, UInt8, Int16, UInt16, Int, Int32, UInt32, Int64, UInt64, Float32, Float64, Float, Range) 2 | import streamBasic(FlushHelperClass) 3 | 4 | var cout: ConsoleOutputStream 5 | 6 | datatype ConsoleOutputStream 7 | ; 8 | 9 | fun <<<(this: ConsoleOutputStream, x: Number) { _Impl.write(x) } 10 | fun <<<(this: ConsoleOutputStream, x: Char) { _Impl.write(x) } 11 | fun <<<(this: ConsoleOutputStream, x: Bool) { if x ; this <<< "true" else this <<< "false" } 12 | fun <<<(this: ConsoleOutputStream, x: StringRef) { for c = x { _Impl.write(c) } } 13 | 14 | // This stream supports flush 15 | [protected] 16 | fun flush(this: ConsoleOutputStream, x: FlushHelperClass) { _Impl.flushOutput } 17 | 18 | package _Impl 19 | [native("writeInt8")] fun write(x: Int8) 20 | [native("writeInt8")] fun write(x: UInt8) 21 | [native("writeInt16")] fun write(x: Int16) 22 | [native("writeInt16")] fun write(x: UInt16) 23 | [native("writeInt32")] fun write(x: Int32) 24 | [native("writeUInt32")] fun write(x: UInt32) 25 | [native("writeInt64")] fun write(x: Int64) 26 | [native("writeUInt64")] fun write(x: UInt64) 27 | [native("writeFloat32")] fun write(x: Float32) 28 | [native("writeFloat64")] fun write(x: Float64) 29 | [native("writeChar")] fun write(x: Char) 30 | 31 | [native("flushOutput")] fun flushOutput 32 | 33 | -------------------------------------------------------------------------------- /SparrowImplicitLib/sprCore/mainImpl.spr: -------------------------------------------------------------------------------- 1 | [native("main"), noInline] 2 | fun main(argc: Int, args: @ @Char): Int 3 | programArgs.ctor(argc, args) 4 | sprMain 5 | return 0 6 | -------------------------------------------------------------------------------- /SparrowImplicitLib/sprCore/stringCvt.spr: -------------------------------------------------------------------------------- 1 | import basicDecls(StringRef, Char, Int, Int64, Float, typeOf) 2 | 3 | fun asInt(src: StringRef) = _StringCvtImpl.atoi(src.cStr()) 4 | fun asInt64(src: StringRef) = _StringCvtImpl.atoll(src.cStr()) 5 | fun asFloat(src: StringRef) = _StringCvtImpl.atof(src.cStr()) 6 | 7 | package _StringCvtImpl 8 | [native("atoi")] fun atoi(str: @Char): Int 9 | [native("atoll")] fun atoll(str: @Char): Int64 10 | [native("atof")] fun atof(str: @Char): Float 11 | -------------------------------------------------------------------------------- /SparrowImplicitLib/std/bitset.spr: -------------------------------------------------------------------------------- 1 | module std.bitset 2 | 3 | import array(Array) 4 | import bitOper 5 | 6 | datatype Bitset 7 | _bits: Array(UInt8) 8 | 9 | [protected] 10 | fun ctor(this: !Bitset, noBits: Int) 11 | _bits.ctor(1 + (noBits-1)/8, UInt8(0)) 12 | 13 | fun setBit(this: !Bitset, n: Int) 14 | _bits(n/8) = _bits(n/8) !|! (UInt8(1) !<>(this: Ptr, os: !OutStream) if isValid(os << #$ValueType) 28 | if ( _ptr !== null ) 29 | os << "Ptr(" << _ptr << ")" 30 | else 31 | os << "Ptr(null)" 32 | os << flush 33 | 34 | fun .(this: Ptr) = _ptr 35 | 36 | fun mkPtr(v: @AnyType) = Ptr(-@typeOf(v))(v) 37 | fun reinterpretPtr(t: Type, ptr: Ptr): Ptr(t) 38 | return Ptr(t)(reinterpretCast(@t, ptr.get())) 39 | -------------------------------------------------------------------------------- /SparrowImplicitLib/std/rMath.spr: -------------------------------------------------------------------------------- 1 | module std.rMath 2 | 3 | import math(sqrt) 4 | import algorithms(foldLeft) 5 | 6 | fun sqr n = n*n 7 | 8 | fun sum(r: Range) = foldLeft(r, (fun x,y = x+y), r.RetType(0)) 9 | 10 | fun mean(r: Range): Float if Number(#$r.RetType) 11 | var sum: r.RetType = 0 12 | var count = 0 13 | for x = r 14 | sum += x 15 | ++count 16 | return Float(sum) / Float(count) 17 | 18 | fun rootMeanSquare r = sqrt(mean(r map \sqr)) 19 | -------------------------------------------------------------------------------- /SparrowImplicitLib/std/scopedPtr.spr: -------------------------------------------------------------------------------- 1 | module std.scopedPtr 2 | 3 | import newDelete(delete) 4 | 5 | [initCtor] 6 | datatype ScopedPtr(type: Type) 7 | using ValueType = type 8 | 9 | _ref: @ValueType 10 | 11 | [protected] 12 | fun dtor(this: !ScopedPtr) 13 | delete(_ref) 14 | 15 | fun get(this: ScopedPtr): @ValueType = _ref 16 | fun isNull(this: ScopedPtr) = _ref === null 17 | fun isSet(this: ScopedPtr) = _ref !== null 18 | 19 | fun reset(this: !ScopedPtr) { delete(_ref); _ref := null } 20 | fun reset(this: !ScopedPtr, ref: !this.ValueType) { delete(this._ref); this._ref := mutToPtr(ref) } 21 | 22 | fun swap(this: !ScopedPtr, other: !typeOf(this)) 23 | let tmp: @ValueType = other._ref 24 | 25 | other._ref := _ref 26 | _ref := tmp 27 | -------------------------------------------------------------------------------- /SparrowImplicitLib/std/typeTraits.spr: -------------------------------------------------------------------------------- 1 | module std.typeTraits 2 | 3 | import defaultHashFunction(defaultHash) 4 | 5 | datatype DefaultTypeTraits 6 | ; 7 | 8 | [protected] 9 | fun equal(this: DefaultTypeTraits, l, r: AnyType) = l == r 10 | fun less(this: DefaultTypeTraits, l, r: AnyType) = l < r 11 | fun hash(this: DefaultTypeTraits, val: AnyType): UInt64 12 | [ct] if ( isValid(UInt64(val hash)) ) 13 | return UInt64(val hash) 14 | else [ct] if ( isValid(UInt64(val.get hash)) ) 15 | return UInt64(val.get hash) 16 | else 17 | return defaultHash(val) 18 | 19 | -------------------------------------------------------------------------------- /SparrowImplicitLib/std/utils.spr: -------------------------------------------------------------------------------- 1 | module std.utils 2 | 3 | concept Nullable(x) if ( 4 | typeOf(x.isSet) == Bool 5 | && typeOf(x.isNull) == Bool 6 | ) 7 | 8 | fun ! (obj: Nullable): Bool = obj.isNull -------------------------------------------------------------------------------- /SparrowImplicitLib/time.spr: -------------------------------------------------------------------------------- 1 | module time 2 | 3 | [native("clock")] fun clock: Int32 4 | 5 | datatype Timer 6 | _startTime: Int32 7 | 8 | fun ctor(this: !Timer) { _startTime = clock } 9 | 10 | fun elapsed(this: Timer) = Float(clock - _startTime) / 1000.0 11 | fun restart(this: !Timer) { _startTime = clock } 12 | -------------------------------------------------------------------------------- /build/.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore everything in this directory 2 | * 3 | # Except this file 4 | !.gitignore 5 | -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | # Minimal makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line. 5 | SPHINXOPTS = 6 | SPHINXBUILD = sphinx-build 7 | SPHINXPROJ = sparrow-lang 8 | SOURCEDIR = . 9 | BUILDDIR = _build 10 | 11 | # Put it first so that "make" without argument is like "make help". 12 | help: 13 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 14 | 15 | .PHONY: help Makefile 16 | 17 | # Catch-all target: route all unknown targets to Sphinx using the new 18 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). 19 | %: Makefile 20 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) -------------------------------------------------------------------------------- /docs/index.rst: -------------------------------------------------------------------------------- 1 | Sparrow language documentation 2 | ============================== 3 | 4 | .. toctree:: 5 | :maxdepth: 2 6 | :caption: Contents: 7 | 8 | introduction 9 | quickstart 10 | tutorials 11 | langFeatures 12 | 13 | 14 | 15 | Indices and tables 16 | ================== 17 | 18 | * :ref:`genindex` 19 | * :ref:`modindex` 20 | * :ref:`search` 21 | -------------------------------------------------------------------------------- /docs/lang/basicExpressions.rst: -------------------------------------------------------------------------------- 1 | .. highlight:: sparrow 2 | 3 | Basic expressions 4 | ================= 5 | 6 | - lambda expressions 7 | - parenthesis expression 8 | - identifiers 9 | - literals: null, true, false, integers, floating point, char, string 10 | - function applications 11 | - compound expressions 12 | 13 | 14 | TODO 15 | 16 | Syntax 17 | ------ 18 | 19 | TODO 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /docs/lang/generatedAssocFun.rst: -------------------------------------------------------------------------------- 1 | .. highlight:: sparrow 2 | 3 | Generated associated functions 4 | ============================== 5 | 6 | UNDER CONSTRUCTION 7 | 8 | For each type, the compiler will attempt generate the following associated functions: 9 | 10 | - initialization constructor (if required) 11 | - default constructor 12 | - copy constructor 13 | - constructor to convert from compile-time to run-time 14 | - destructor 15 | - the ``=`` assignment operator 16 | - the ``==`` equality check operator 17 | 18 | TODO -------------------------------------------------------------------------------- /docs/lang/generics.rst: -------------------------------------------------------------------------------- 1 | .. highlight:: sparrow 2 | 3 | Generics 4 | ======== 5 | 6 | UNDER CONSTRUCTION 7 | 8 | There are three types of generics in Sparrow: 9 | 10 | - package generics 11 | - datatype generics 12 | - function generics 13 | 14 | TODO -------------------------------------------------------------------------------- /docs/langFeatures.rst: -------------------------------------------------------------------------------- 1 | Language features 2 | ================= 3 | 4 | .. toctree:: 5 | :maxdepth: 1 6 | 7 | lang/modules 8 | lang/declarations 9 | lang/generatedAssocFun 10 | lang/generics 11 | lang/basicExpressions 12 | lang/operators 13 | lang/modifiers 14 | 15 | This section is still under development. 16 | -------------------------------------------------------------------------------- /docs/make.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | pushd %~dp0 4 | 5 | REM Command file for Sphinx documentation 6 | 7 | if "%SPHINXBUILD%" == "" ( 8 | set SPHINXBUILD=sphinx-build 9 | ) 10 | set SOURCEDIR=. 11 | set BUILDDIR=_build 12 | set SPHINXPROJ=sparrow-lang 13 | 14 | if "%1" == "" goto help 15 | 16 | %SPHINXBUILD% >NUL 2>NUL 17 | if errorlevel 9009 ( 18 | echo. 19 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx 20 | echo.installed, then set the SPHINXBUILD environment variable to point 21 | echo.to the full path of the 'sphinx-build' executable. Alternatively you 22 | echo.may add the Sphinx directory to PATH. 23 | echo. 24 | echo.If you don't have Sphinx installed, grab it from 25 | echo.http://sphinx-doc.org/ 26 | exit /b 1 27 | ) 28 | 29 | %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% 30 | goto end 31 | 32 | :help 33 | %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% 34 | 35 | :end 36 | popd 37 | -------------------------------------------------------------------------------- /docs/tut/thesis.rst: -------------------------------------------------------------------------------- 1 | PhD thesis documentation [slightly outdated] 2 | ============================================ 3 | 4 | - See the `PhD presentation `_ (accompanied by `this video `_) 5 | - Read the `PhD thesis on Sparrow `_ 6 | 7 | These present a slightly outdated version of Sparrow, but nevertheless it provides a good tour of Sparrow's most important features, with multiple examples and measurements. It also contains the design rationale for Sparrow. -------------------------------------------------------------------------------- /docs/tutorials.rst: -------------------------------------------------------------------------------- 1 | Tutorials 2 | ========= 3 | 4 | .. toctree:: 5 | tut/thesis 6 | tut/beginnerIntoToSparrow 7 | 8 | This section is still under development. 9 | -------------------------------------------------------------------------------- /hooks/post_checkout: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | git submodule update --init --recursive 3 | -------------------------------------------------------------------------------- /others/sublime/Comments.tmPreferences: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | scope 5 | source.sparrow 6 | settings 7 | 8 | shellVariables 9 | 10 | 11 | name 12 | TM_COMMENT_START 13 | value 14 | /* 15 | 16 | 17 | name 18 | TM_COMMENT_END 19 | value 20 | */ 21 | 22 | 23 | name 24 | TM_COMMENT_MODE 25 | value 26 | block 27 | 28 | 29 | name 30 | TM_COMMENT_DISABLE_INDENT 31 | value 32 | yes 33 | 34 | 35 | name 36 | TM_COMMENT_START_2 37 | value 38 | // 39 | 40 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /others/sublime/Indentation Rules.tmPreferences: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | scope 5 | source.sparrow 6 | settings 7 | 8 | increaseIndentPattern 9 | ^.*\{[^}"']*$ 10 | decreaseIndentPattern 11 | ^(.*\*/)?\s*\}([^}{"']*\{)?[;\s]*(//.*|/\*.*\*/\s*)?$ 12 | 13 | bracketIndentNextLinePattern 14 | (?x) 15 | ^ \s* \b(if|while|else|for|class|datatype|fun)\b [^;]* $ 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /others/sublime/Snippets/class.sublime-snippet: -------------------------------------------------------------------------------- 1 | 2 | 12 | class 13 | source.sparrow 14 | class … { … } 15 | 16 | -------------------------------------------------------------------------------- /others/sublime/Snippets/concept.sublime-snippet: -------------------------------------------------------------------------------- 1 | 2 | 7 | concept 8 | source.sparrow 9 | concept … if … 10 | 11 | -------------------------------------------------------------------------------- /others/sublime/Snippets/datatype.sublime-snippet: -------------------------------------------------------------------------------- 1 | 2 | 7 | datatype 8 | source.sparrow 9 | datatype … = … 10 | 11 | -------------------------------------------------------------------------------- /others/sublime/Snippets/datatype2.sublime-snippet: -------------------------------------------------------------------------------- 1 | 2 | 7 | datatype= 8 | source.sparrow 9 | datatype … { … } 10 | 11 | -------------------------------------------------------------------------------- /others/sublime/Snippets/for.sublime-snippet: -------------------------------------------------------------------------------- 1 | 2 | 5 | for 6 | source.sparrow 7 | for var = range { … } 8 | 9 | -------------------------------------------------------------------------------- /others/sublime/Snippets/fun.sublime-snippet: -------------------------------------------------------------------------------- 1 | 2 | 8 | fun 9 | source.sparrow 10 | fun … { … } 11 | 12 | -------------------------------------------------------------------------------- /others/sublime/Snippets/if-else.sublime-snippet: -------------------------------------------------------------------------------- 1 | 2 | 7 | ife 8 | source.sparrow 9 | if … {} else {} 10 | 11 | -------------------------------------------------------------------------------- /others/sublime/Snippets/if.sublime-snippet: -------------------------------------------------------------------------------- 1 | 2 | 5 | if 6 | source.sparrow 7 | if … {} 8 | 9 | -------------------------------------------------------------------------------- /others/sublime/Snippets/import.sublime-snippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | im 4 | source.sparrow 5 | import … 6 | 7 | -------------------------------------------------------------------------------- /others/sublime/Snippets/package.sublime-snippet: -------------------------------------------------------------------------------- 1 | 2 | 5 | package 6 | source.sparrow 7 | package … {} 8 | 9 | -------------------------------------------------------------------------------- /others/sublime/Snippets/return.sublime-snippet: -------------------------------------------------------------------------------- 1 | 2 | 3 | ret 4 | source.sparrow 5 | return … 6 | 7 | -------------------------------------------------------------------------------- /others/sublime/Snippets/while-step.sublime-snippet: -------------------------------------------------------------------------------- 1 | 2 | 5 | while-step 6 | source.sparrow 7 | while … ; … { … } 8 | 9 | -------------------------------------------------------------------------------- /others/sublime/Snippets/while.sublime-snippet: -------------------------------------------------------------------------------- 1 | 2 | 5 | while 6 | source.sparrow 7 | while … { … } 8 | 9 | -------------------------------------------------------------------------------- /others/sublime/Sparrow.sublime-build: -------------------------------------------------------------------------------- 1 | { 2 | "cmd": ["/Users/lucteo/work/sparrow/build/bin/SparrowCompiler", "--simple-linking", "--noColors", "${file}"], 3 | "working_dir": "${file_path}", 4 | "file_regex": "^(.*?)\\(([0-9]+)\\:([0-9]+)\\s*\\-\\s*[0-9]+:?[0-9]*\\) : (.*)$", 5 | "selector": "source.sparrow" 6 | } 7 | -------------------------------------------------------------------------------- /others/sublime/SymbolList-AddSpaces.tmPreferences: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | scope 5 | source.sparrow meta.class,source.sparrow meta.concept,source.sparrow meta.function,source.sparrow meta.namespace 6 | settings 7 | 8 | showInSymbolList 9 | 1 10 | symbolTransformation 11 | 12 | s/(\s*)(?:\[.*\])?\s*class\s*(.+)/$1$2/f; 13 | s/(\s*)(?:\[.*\])?\s*datatype\s*(.+)/$1$2/f; 14 | s/(\s*)(?:\[.*\])?\s*concept\s*(.+)/$1$2/f; 15 | s/(\s*)(?:\[.*\])?\s*fun\s*(.+)/$1$2 \(...\)/f; 16 | s/(\s*)(?:\[.*\])?\s*package\s*(.+)/$1$2/f; 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /others/sublime/SymbolList-HideVars.tmPreferences: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | scope 5 | source.sparrow entity.name.variable 6 | settings 7 | 8 | showInSymbolList 9 | 0 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/Feather/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | # The source files 3 | SET(sourceFiles 4 | "Api/Feather.h" 5 | 6 | "Utils/FeatherUtils.h" 7 | "Utils/FeatherUtils.hpp" 8 | "Utils/cppif/FeatherTypes.hpp" 9 | 10 | "src/CtApiFunctions.h" 11 | "src/CtApiFunctions.cpp" 12 | "src/FeatherNodeCommonsCpp.h" 13 | "src/FeatherNodeCommonsH.h" 14 | "src/StdInc.h" 15 | "src/Api/Feather.c" 16 | "src/Api/Feather_Nodes.cpp" 17 | "src/Api/Feather_Nodes.h" 18 | "src/Api/Feather_Types.cpp" 19 | "src/Api/Feather_Types.h" 20 | "src/Utils/FeatherUtils.c" 21 | "src/Utils/FeatherUtils.cpp" 22 | "src/Utils/cppif/FeatherTypes.cpp" 23 | "src/Utils/cppif/FeatherNodes.cpp" 24 | ) 25 | 26 | # Project settings 27 | INCLUDE_DIRECTORIES( "." ) 28 | INCLUDE_DIRECTORIES( ".." ) 29 | ADD_DEFINITIONS( "-DINSIDE_FEATHER" ) 30 | ADD_SOURCES_TO_GROUPS(sourceFiles) 31 | 32 | ADD_LIBRARY( Feather ${sourceFiles} ) 33 | -------------------------------------------------------------------------------- /src/Feather/Utils/FeatherUtils.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Feather/Utils/FeatherUtils.h" 4 | 5 | #include "Nest/Api/EvalMode.h" 6 | #include "Nest/Api/StringRef.h" 7 | #include "Nest/Api/Location.h" 8 | #include "Nest/Utils/NodeUtils.h" 9 | #include "Nest/Utils/cppif/StringRef.hpp" 10 | #include "Nest/Utils/cppif/Type.hpp" 11 | 12 | using Node = struct Nest_Node; 13 | using CompilationContext = struct Nest_CompilationContext; 14 | 15 | using Nest::Location; 16 | using Nest::StringRef; 17 | using Nest::Type; 18 | 19 | /// Getter for the value memory buffer of this value 20 | template T* Feather_getCtValueData(Node* ctVal) { 21 | return (T*)(void*)Nest_getCheckPropertyString(ctVal, "valueData").begin; 22 | } 23 | 24 | template Node* Feather_mkCtValueT(const Location& loc, Type type, T* dataVal) { 25 | // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast) 26 | const auto* p = reinterpret_cast(dataVal); 27 | StringRef dataStr = {p, p + sizeof(*dataVal)}; 28 | return Feather_mkCtValue(loc, type, dataStr); 29 | } 30 | -------------------------------------------------------------------------------- /src/Feather/src/Api/Feather.c: -------------------------------------------------------------------------------- 1 | #include "Feather/Api/Feather.h" 2 | 3 | #include "Feather/src/Api/Feather_Types.h" 4 | #include "Feather/src/Api/Feather_Nodes.h" 5 | #include "Feather/src/CtApiFunctions.h" 6 | 7 | #include "Nest/Api/CompilerModule.h" 8 | 9 | void _Feather_initModule() { 10 | initFeatherTypeKinds(); 11 | initFeatherNodeKinds(); 12 | } 13 | 14 | void _Feather_onBackendSetFun(Nest_Backend* backend) { 15 | // Register the CT API functions 16 | Feather_registerCtApiFunctions(backend); 17 | } 18 | 19 | static Nest_CompilerModule theFeatherModule = {"Feather", 20 | "Module that defines the basic node kinds for the compilers; it provides a minimal, C-like " 21 | "node set to be the base of more complex languages", 22 | "LucTeo", "www.lucteo.ro", 1, 0, &_Feather_initModule, 0, &_Feather_onBackendSetFun}; 23 | 24 | Nest_CompilerModule* Feather_getModule() { return &theFeatherModule; } -------------------------------------------------------------------------------- /src/Feather/src/Api/Feather_Nodes.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifdef __cplusplus 4 | extern "C" { 5 | #endif 6 | 7 | /// Called to initialize the Feather node kinds 8 | void initFeatherNodeKinds(); 9 | 10 | #ifdef __cplusplus 11 | } 12 | #endif 13 | -------------------------------------------------------------------------------- /src/Feather/src/Api/Feather_Types.cpp: -------------------------------------------------------------------------------- 1 | #include "Feather/src/StdInc.h" 2 | #include "Feather/src/Api/Feather_Types.h" 3 | #include "Feather/Api/Feather.h" 4 | #include "Feather/Utils/FeatherUtils.hpp" 5 | #include "Feather/Utils/cppif/FeatherTypes.hpp" 6 | 7 | using namespace Feather; 8 | 9 | int typeKindVoid = -1; 10 | int typeKindData = -1; 11 | int typeKindPtr = -1; 12 | int typeKindConst = -1; 13 | int typeKindMutable = -1; 14 | int typeKindTemp = -1; 15 | int typeKindArray = -1; 16 | int typeKindFunction = -1; 17 | 18 | void initFeatherTypeKinds() { 19 | typeKindVoid = VoidType::registerTypeKind(); 20 | typeKindData = DataType::registerTypeKind(); 21 | typeKindPtr = PtrType::registerTypeKind(); 22 | typeKindConst = ConstType::registerTypeKind(); 23 | typeKindMutable = MutableType::registerTypeKind(); 24 | typeKindTemp = TempType::registerTypeKind(); 25 | typeKindArray = ArrayType::registerTypeKind(); 26 | typeKindFunction = FunctionType::registerTypeKind(); 27 | } 28 | -------------------------------------------------------------------------------- /src/Feather/src/Api/Feather_Types.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifdef __cplusplus 4 | extern "C" { 5 | #endif 6 | 7 | /// Called to initialize the Feather type kinds 8 | void initFeatherTypeKinds(); 9 | 10 | #ifdef __cplusplus 11 | } 12 | #endif 13 | -------------------------------------------------------------------------------- /src/Feather/src/CtApiFunctions.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifdef __cplusplus 4 | extern "C" { 5 | #endif 6 | 7 | typedef struct Nest_Backend Nest_Backend; 8 | 9 | void Feather_registerCtApiFunctions(Nest_Backend* backend); 10 | 11 | #ifdef __cplusplus 12 | } 13 | #endif 14 | -------------------------------------------------------------------------------- /src/Feather/src/FeatherNodeCommonsCpp.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "FeatherNodeCommonsH.h" 4 | #include "Feather/Api/Feather.h" 5 | #include "Feather/Utils/FeatherUtils.h" 6 | 7 | #include "Nest/Utils/Diagnostic.hpp" 8 | #include "Nest/Api/CompilationContext.h" 9 | #include "Nest/Api/Type.h" 10 | #include "Nest/Api/SymTab.h" 11 | #include "Nest/Api/Modifier.h" 12 | 13 | namespace Feather {}; 14 | 15 | using namespace Feather; 16 | using namespace Nest; 17 | -------------------------------------------------------------------------------- /src/Feather/src/FeatherNodeCommonsH.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Nest/Api/SymTab.h" 4 | #include "Nest/Api/Type.h" 5 | #include "Nest/Api/EvalMode.h" 6 | 7 | #include "Feather/Api/Feather.h" 8 | 9 | typedef struct Nest_Modifier Nest_Modifier; 10 | -------------------------------------------------------------------------------- /src/Feather/src/StdInc.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Nest/Utils/DefaultStdInc.hpp" 4 | 5 | #include "Nest/Api/Compiler.h" 6 | #include "Nest/Api/Location.h" 7 | #include "Nest/Api/Type.h" 8 | #include "Nest/Api/CompilationContext.h" 9 | #include "Nest/Utils/cppif/Fwd.hpp" 10 | #include "Nest/Utils/cppif/NodeUtils.hpp" 11 | 12 | // Common functions, exposed 13 | 14 | // TODO: remove these 15 | using Nest::all; 16 | using Nest::allM; 17 | using Nest::at; 18 | using Nest::begin; 19 | using Nest::end; 20 | using Nest::fromIniList; 21 | using Nest::size; 22 | -------------------------------------------------------------------------------- /src/LLVMBackend/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | # The source files 3 | SET(sourceFiles 4 | "StdInc.h" 5 | "LLVMBackendMod.h" 6 | "LLVMBackendMod.cpp" 7 | "LLVMBackend.h" 8 | "LLVMBackend.cpp" 9 | "LLVMSourceCode.h" 10 | "LLVMSourceCode.cpp" 11 | "Generator.h" 12 | "Generator.cpp" 13 | "Module.h" 14 | "Module.cpp" 15 | "RtModule.h" 16 | "RtModule.cpp" 17 | "CtModule.h" 18 | "CtModule.cpp" 19 | "DataLayoutHelper.h" 20 | "DataLayoutHelper.cpp" 21 | "Tr/TrContext.h" 22 | "Tr/TrContext.cpp" 23 | "Tr/Scope.h" 24 | "Tr/Scope.cpp" 25 | "Tr/Instruction.h" 26 | "Tr/Instruction.cpp" 27 | "Tr/DebugInfo.h" 28 | "Tr/DebugInfo.cpp" 29 | "Tr/TrType.h" 30 | "Tr/TrType.cpp" 31 | "Tr/TrTopLevel.h" 32 | "Tr/TrTopLevel.cpp" 33 | "Tr/TrFunction.h" 34 | "Tr/TrFunction.cpp" 35 | "Tr/TrLocal.h" 36 | "Tr/TrLocal.cpp" 37 | "Tr/LlvmBuilder.h" 38 | "Tr/PrepareTranslate.h" 39 | "Tr/PrepareTranslate.cpp" 40 | ) 41 | 42 | # Project settings 43 | INCLUDE_DIRECTORIES( "." ) 44 | INCLUDE_DIRECTORIES( ".." ) 45 | ADD_DEFINITIONS( "-DINSIDE_LLVMBACKEND" ) 46 | ADD_SOURCES_TO_GROUPS(sourceFiles) 47 | 48 | ADD_LIBRARY( LLVMBackend ${sourceFiles} ) 49 | TARGET_LINK_LIBRARIES(LLVMBackend ${REQ_LLVM_LIBRARIES}) 50 | -------------------------------------------------------------------------------- /src/LLVMBackend/DataLayoutHelper.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Nest/Utils/cppif/Type.hpp" 4 | 5 | #include 6 | 7 | FWD_CLASS1(llvm, LLVMContext); 8 | FWD_CLASS1(llvm, Module); 9 | 10 | namespace LLVMB { 11 | 12 | using Nest::Type; 13 | 14 | /// Class that is responsible for computing the sizeOf and alignOf data types 15 | class DataLayoutHelper { 16 | public: 17 | DataLayoutHelper(); 18 | ~DataLayoutHelper(); 19 | 20 | /// Get the size of the given type in bytes, according to the current data layout 21 | size_t getSizeOf(Type type); 22 | 23 | /// Get the alignment of the given type in bytes, according to the current data layout 24 | size_t getAlignOf(Type type); 25 | 26 | private: 27 | unique_ptr llvmContext_; 28 | unique_ptr llvmModule_; 29 | 30 | unordered_map sizesOfTypes_; 31 | unordered_map alignmentsOfTypes_; 32 | }; 33 | 34 | } // namespace LLVMB 35 | -------------------------------------------------------------------------------- /src/LLVMBackend/Generator.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | FWD_CLASS1(llvm, Module); 7 | 8 | namespace LLVMB { 9 | //! Generate LLVM assembly file for the given run-time module 10 | void generateRtAssembly(const llvm::Module& module); 11 | 12 | //! Generate LLVM assembly for the given CT module. 13 | //! Because during the compilation time we will process multiple LLVM modules, this function 14 | //! will be called multiple times, for each such module. Instead of writing the CT assembly to a 15 | //! single file, we instead write a lot of .ll files in a directory. 16 | void generateCtAssembly(const llvm::Module& module); 17 | 18 | /// Link the given input module to produce a final binary, as native executable 19 | void link(const vector& inputs, const string& outFilename); 20 | } // namespace LLVMB 21 | -------------------------------------------------------------------------------- /src/LLVMBackend/LLVMBackend.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /// Register the LLVM backend 4 | int LLVMBe_registerLLVMBackend(); 5 | -------------------------------------------------------------------------------- /src/LLVMBackend/LLVMBackendMod.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "LLVMBackendMod.h" 3 | #include "LLVMSourceCode.h" 4 | #include "LLVMBackend.h" 5 | 6 | #include "Nest/Api/CompilerModule.h" 7 | 8 | void LLVMBackend_initModule() { 9 | LLVMBe_registerLLVMSourceCode(); 10 | LLVMBe_registerLLVMBackend(); 11 | } 12 | 13 | Nest_CompilerModule* getLLVMBackendModule() { 14 | // NOLINTNEXTLINE(cppcoreguidelines-owning-memory) 15 | auto* nestModule = 16 | new Nest_CompilerModule{"LLVMBackend", "Backend that uses LLVM to generate code", 17 | "LucTeo", "www.lucteo.ro", 1, 0, &LLVMBackend_initModule, nullptr, nullptr}; 18 | return nestModule; 19 | } -------------------------------------------------------------------------------- /src/LLVMBackend/LLVMBackendMod.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | typedef struct Nest_CompilerModule Nest_CompilerModule; 4 | 5 | /// Getter for the LLVMBackend module 6 | Nest_CompilerModule* getLLVMBackendModule(); -------------------------------------------------------------------------------- /src/LLVMBackend/LLVMSourceCode.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /// The kind of the FSimple source code 4 | extern int LLVMBe_kindLLVMSourceCode; 5 | 6 | /// Register the LLVM source code 7 | void LLVMBe_registerLLVMSourceCode(); 8 | -------------------------------------------------------------------------------- /src/LLVMBackend/Module.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "Module.h" 3 | #include 4 | 5 | #include "Feather/Utils/FeatherUtils.hpp" 6 | 7 | #include "Nest/Utils/CompilerSettings.hpp" 8 | #include "Nest/Api/Compiler.h" 9 | 10 | using namespace LLVMB; 11 | 12 | Module::Module(const string& name) 13 | : llvmContext_(new llvm::LLVMContext()) {} 14 | 15 | Module::~Module() = default; 16 | 17 | bool Module::canUse(Node* decl) const { 18 | EvalMode mode = Feather_effectiveEvalMode(decl); 19 | ASSERT(mode != modeUnspecified); 20 | return mode != modeCt || isCt(); 21 | } 22 | -------------------------------------------------------------------------------- /src/LLVMBackend/StdInc.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Nest/Utils/DefaultStdInc.hpp" 4 | #include "Nest/Utils/cppif/Fwd.hpp" 5 | #include "Nest/Utils/cppif/NodeUtils.hpp" 6 | 7 | // Common functions, exposed 8 | 9 | // TODO: remove these 10 | using Nest::all; 11 | using Nest::allM; 12 | using Nest::at; 13 | using Nest::begin; 14 | using Nest::end; 15 | using Nest::fromIniList; 16 | using Nest::size; 17 | 18 | #include "llvm/IR/LLVMContext.h" 19 | #include "llvm/IR/Module.h" 20 | #include 21 | #include 22 | -------------------------------------------------------------------------------- /src/LLVMBackend/Tr/Instruction.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "Instruction.h" 3 | #include "Scope.h" 4 | #include "TrContext.h" 5 | #include "TrLocal.h" 6 | 7 | #include "Nest/Utils/Diagnostic.hpp" 8 | 9 | using namespace LLVMB; 10 | using namespace LLVMB::Tr; 11 | using namespace Nest; 12 | 13 | namespace { 14 | Scope& scopeFromContext(TrContext& context) { 15 | ASSERT(!context.scopesStack().empty()); 16 | return *context.scopesStack().back(); 17 | } 18 | } // namespace 19 | 20 | Instruction::Instruction(TrContext& context) 21 | : scope_(scopeFromContext(context)) { 22 | scope_.instructionsStack().push_back(this); 23 | } 24 | 25 | Instruction::~Instruction() { 26 | ASSERT(!scope_.instructionsStack().empty()); 27 | ASSERT(scope_.instructionsStack().back() == this); 28 | outputDestructActions(); 29 | scope_.instructionsStack().pop_back(); 30 | } 31 | 32 | void Instruction::addTempDestructAction(Node* destructAction) { 33 | destructActions_.push_back(destructAction); 34 | } 35 | 36 | void Instruction::outputDestructActions() { 37 | for (Node* n : boost::adaptors::reverse(destructActions_)) { 38 | translateNode(n, scope_.context()); 39 | } 40 | } 41 | 42 | NodeVector Instruction::stealDestructActions() { 43 | NodeVector res; 44 | res.swap(destructActions_); 45 | return res; 46 | } 47 | -------------------------------------------------------------------------------- /src/LLVMBackend/Tr/Instruction.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Nest/Utils/cppif/NodeUtils.hpp" 4 | 5 | FWD_CLASS2(LLVMB, Tr, Scope); 6 | FWD_CLASS2(LLVMB, Tr, TrContext); 7 | 8 | namespace LLVMB { 9 | namespace Tr { 10 | 11 | using Nest::Node; 12 | using Nest::NodeVector; 13 | 14 | /// Represents a Instruction in function body, inside a Scope 15 | /// 16 | /// An object of this class adds itself automatically to the Scope on constructor and removes itself 17 | /// from Scope in destructor. Therefore these are intended to be used as scoped objects actions 18 | /// 19 | /// This object contains the list of temporary destruct actions that need to be executed (in reverse 20 | /// order) when the instruction finishes. 21 | /// 22 | /// \see Scope, TrContext 23 | class Instruction { 24 | public: 25 | Instruction(TrContext& context); 26 | ~Instruction(); 27 | 28 | /// Adds an temporary destruct action 29 | void addTempDestructAction(Node* destructAction); 30 | 31 | /// Translate the destruct actions corresponding to this node 32 | void outputDestructActions(); 33 | 34 | /// Returns the list of destruct actions and removes them from the current instruction 35 | NodeVector stealDestructActions(); 36 | 37 | protected: 38 | Scope& scope_; 39 | NodeVector destructActions_; 40 | }; 41 | } // namespace Tr 42 | } // namespace LLVMB 43 | -------------------------------------------------------------------------------- /src/LLVMBackend/Tr/LlvmBuilder.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "llvm/IR/IRBuilder.h" 4 | 5 | namespace LLVMB { 6 | namespace Tr { 7 | typedef llvm::IRBuilder<> LlvmBuilder; 8 | } 9 | } // namespace LLVMB -------------------------------------------------------------------------------- /src/LLVMBackend/Tr/PrepareTranslate.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | using Nest::Node; 4 | 5 | namespace LLVMB { 6 | namespace Tr { 7 | 8 | struct GlobalContext; 9 | 10 | //! Makes sure that the given node is translatable. 11 | //! 12 | //! Walks over all the children nodes and make sure they are compiled. If we find nodes that refer 13 | //! to other top-level nodes, make sure these are compiled and prepared for translation. 14 | //! 15 | //! After calling this function, there should be no node that is not semantically checked, which is 16 | //! directly or indirectly needed by the translation of node. 17 | void prepareTranslate(Node* node, GlobalContext& ctx); 18 | 19 | } // namespace Tr 20 | } // namespace LLVMB -------------------------------------------------------------------------------- /src/LLVMBackend/Tr/TrFunction.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Feather/Api/Feather.h" 4 | 5 | namespace llvm { 6 | class Function; 7 | } 8 | 9 | namespace LLVMB { 10 | 11 | namespace Tr { 12 | 13 | struct GlobalContext; 14 | using Nest::Node; 15 | 16 | //! Main function used to translate a feather function into LLVM IR. 17 | //! It will translate the definition of the function, if not already translated. 18 | llvm::Function* translateFunction(Node* node, GlobalContext& ctx); 19 | 20 | //! Create/translate a function that calls the given node. 21 | //! 22 | //! If 'expectsResult' is set, we add the type of the node as a pointer param to the function, and 23 | //! we make the function store the result there. If false, this will be a void() function. 24 | //! 25 | //! The definition of this will be placed in 'ctx.llvmModule_'. All the other referenced definitions 26 | //! will be placed in 'ctx.definitionsLlvmModule_'. 27 | llvm::Function* makeFunThatCalls( 28 | Node* node, GlobalContext& ctx, const char* funName, bool expectsResult = false); 29 | 30 | //! Translate a function calling conversion; used for function calls 31 | llvm::CallingConv::ID translateCallingConv(CallConvention conv); 32 | 33 | } // namespace Tr 34 | } // namespace LLVMB 35 | -------------------------------------------------------------------------------- /src/LLVMBackend/Tr/TrLocal.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | FWD_CLASS1(LLVMB, Module) 4 | FWD_CLASS2(LLVMB, Tr, TrContext) 5 | 6 | FWD_CLASS1(llvm, LLVMContext); 7 | FWD_CLASS1(llvm, Module); 8 | FWD_CLASS1(llvm, BasicBlock); 9 | FWD_CLASS1(llvm, Value); 10 | FWD_CLASS1(llvm, Function); 11 | 12 | namespace LLVMB { 13 | namespace Tr { 14 | 15 | using Nest::Node; 16 | 17 | /// Called to translate a local node; returns the llvm value corresponding to the node 18 | llvm::Value* translateNode(Node* node, TrContext& context); 19 | 20 | /// Sets the given llvm value as attribute to the node; returns the given value 21 | llvm::Value* setValue(TrContext& context, Node& node, llvm::Value* val); 22 | 23 | /// Gets the LLVM value associated with a node; returns null if no value is associated 24 | llvm::Value* getValue(TrContext& context, Node& node, bool doCheck = true); 25 | } // namespace Tr 26 | } // namespace LLVMB 27 | -------------------------------------------------------------------------------- /src/LLVMBackend/Tr/TrTopLevel.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace llvm { 4 | class Type; 5 | class Module; 6 | } // namespace llvm 7 | 8 | namespace LLVMB { 9 | class Module; 10 | 11 | namespace Tr { 12 | struct GlobalContext; 13 | using Nest::Node; 14 | 15 | //! Main translation method for top-level nodes 16 | void translateTopLevelNode(Node* node, GlobalContext& ctx); 17 | 18 | //! Adds the backend code to the current LLVM global context 19 | void translateBackendCode(Node* node, GlobalContext& ctx); 20 | 21 | //! Translates the given class 22 | llvm::Type* translateClass(Node* node, GlobalContext& ctx); 23 | 24 | //! Translates the given global variable 25 | llvm::Value* translateGlobalVar(Node* node, GlobalContext& ctx); 26 | } // namespace Tr 27 | } // namespace LLVMB 28 | -------------------------------------------------------------------------------- /src/LLVMBackend/Tr/TrType.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Nest/Utils/cppif/Type.hpp" 4 | #include "Nest/Api/StringRef.h" 5 | 6 | using Nest::Location; 7 | using Nest::Node; 8 | using Nest::StringRef; 9 | 10 | namespace llvm { 11 | class Type; 12 | class LLVMContext; 13 | } // namespace llvm 14 | 15 | namespace LLVMB { 16 | 17 | class Module; 18 | 19 | namespace Tr { 20 | 21 | struct GlobalContext; 22 | 23 | //! Translates the given type into LLVM representation. 24 | //! This may generate a new top-level struct in the LLVM module 25 | llvm::Type* getLLVMType(Nest::Type type, GlobalContext& ctx); 26 | 27 | //! Get the LLVM type for a native type 28 | //! If this is not a LLVM native type, it will return null 29 | llvm::Type* getNativeLLVMType( 30 | const Location& loc, StringRef nativeName, llvm::LLVMContext& llvmContext); 31 | 32 | //! Gets the LLVM type corresponding to the given function declaration. 33 | //! May create new top-level entries (struct, fun decls) in the LLVM module. 34 | llvm::Type* getLLVMFunctionType(Node* funDecl, int ignoreArg, GlobalContext& ctx); 35 | 36 | } // namespace Tr 37 | } // namespace LLVMB 38 | -------------------------------------------------------------------------------- /src/Nest/Api/CompilerModule.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | typedef struct Nest_Backend Nest_Backend; 4 | 5 | /** 6 | A module represents a functional block of the compiler. 7 | 8 | One can create modules to implement "any kind" of functionality into the 9 | compiler. Of course, one would like to interact with other modules, so typically 10 | a module interacts with the Nest module. 11 | */ 12 | struct Nest_CompilerModule { 13 | // Module description 14 | const char* name; 15 | const char* description; 16 | const char* author; 17 | const char* url; 18 | int majorVersion; 19 | int minorVersion; 20 | 21 | // Function called to initialize the module 22 | void (*initFun)(); 23 | // Function called when the module is destroyed 24 | void (*destroyFun)(); 25 | 26 | // Function called when the Backend was set 27 | void (*onBackendSetFun)(Nest_Backend*); 28 | }; 29 | typedef struct Nest_CompilerModule Nest_CompilerModule; 30 | -------------------------------------------------------------------------------- /src/Nest/Api/EvalMode.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /// Enumeration that determines the evaluation mode of nodes: rt, ct 4 | enum Nest_EvalMode { 5 | modeUnspecified = 0, 6 | modeRt, //!< Available both at run-time and compile-time, depending on the invocation context 7 | modeCt, //!< Only available at compile-time 8 | }; 9 | 10 | typedef enum Nest_EvalMode Nest_EvalMode; 11 | typedef enum Nest_EvalMode EvalMode; 12 | -------------------------------------------------------------------------------- /src/Nest/Api/Location.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | typedef struct Nest_SourceCode Nest_SourceCode; 4 | 5 | struct Nest_LocationPos { 6 | unsigned int line; ///< Line number (starting with 1) 7 | unsigned int col; ///< Column number (starting with 1) 8 | }; 9 | typedef struct Nest_LocationPos Nest_LocationPos; 10 | 11 | /// A location indicates a region of characters in a particular source code 12 | struct Nest_Location { 13 | const Nest_SourceCode* sourceCode; ///< The source code containing this location 14 | Nest_LocationPos start; ///< The start position in the source code 15 | Nest_LocationPos end; ///< The end position in the source code 16 | }; 17 | 18 | typedef struct Nest_Location Nest_Location; 19 | -------------------------------------------------------------------------------- /src/Nest/Api/Modifier.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | typedef struct Nest_Node Nest_Node; 4 | 5 | enum Nest_ModifierType { 6 | modTypeBeforeSetContext, 7 | modTypeAfterSetContext, 8 | modTypeBeforeComputeType, 9 | modTypeAfterComputeType, 10 | modTypeBeforeSemanticCheck, 11 | modTypeAfterSemanticCheck, 12 | }; 13 | typedef enum Nest_ModifierType Nest_ModifierType; 14 | 15 | typedef struct Nest_Modifier Nest_Modifier; 16 | 17 | typedef void (*FModifierFun)(Nest_Modifier* mod, Nest_Node* node); 18 | 19 | /// Structure defining an interface for a modifier 20 | /// The modifier is called for all the important operations that happen to a node 21 | /// This way, the modifier can change the compilation of the node 22 | struct Nest_Modifier { 23 | Nest_ModifierType modifierType; 24 | FModifierFun modifierFun; 25 | }; 26 | 27 | struct Nest_ModifiersArray { 28 | Nest_Modifier** beginPtr; 29 | Nest_Modifier** endPtr; 30 | Nest_Modifier** endOfStorePtr; 31 | }; 32 | typedef struct Nest_ModifiersArray Nest_ModifiersArray; 33 | -------------------------------------------------------------------------------- /src/Nest/Api/Nest.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifdef __cplusplus 4 | extern "C" { 5 | #endif 6 | 7 | typedef struct Nest_CompilerModule Nest_CompilerModule; 8 | 9 | /// Getter for the Nest module 10 | Nest_CompilerModule* getNestModule(); 11 | 12 | #ifdef __cplusplus 13 | } 14 | #endif 15 | -------------------------------------------------------------------------------- /src/Nest/Api/NodeArray.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | typedef struct Nest_Node Nest_Node; 4 | 5 | /// An array of nodes 6 | struct Nest_NodeArray { 7 | Nest_Node** beginPtr; 8 | Nest_Node** endPtr; 9 | Nest_Node** endOfStorePtr; 10 | }; 11 | typedef struct Nest_NodeArray Nest_NodeArray; 12 | -------------------------------------------------------------------------------- /src/Nest/Api/NodeRange.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /** 4 | * @brief A range of nodes (immutable). 5 | * 6 | * This represents a view on an array of nodes (pointers). 7 | * The nodes in the array cannot be changed through this. But the content of the nodes can be 8 | * mutated. 9 | */ 10 | struct Nest_NodeRange { 11 | struct Nest_Node* const* beginPtr; 12 | struct Nest_Node* const* endPtr; 13 | }; 14 | typedef struct Nest_NodeRange Nest_NodeRange; 15 | 16 | /** 17 | * @brief A range of mutable nodes. 18 | * 19 | * This represents a view on an array of nodes (pointers). 20 | * The nodes in the array, and their pointers can be changed through this. 21 | */ 22 | struct Nest_NodeRangeM { 23 | struct Nest_Node** beginPtr; 24 | struct Nest_Node** endPtr; 25 | }; 26 | typedef struct Nest_NodeRangeM Nest_NodeRangeM; 27 | -------------------------------------------------------------------------------- /src/Nest/Api/SourceCode.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Nest/Api/NodeArray.h" 4 | #include "Nest/Api/StringRef.h" 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | typedef struct Nest_StringRef Nest_StringRef; 11 | typedef struct Nest_CompilationContext Nest_CompilationContext; 12 | typedef struct Nest_Node Nest_Node; 13 | 14 | struct Nest_SourceCode { 15 | int kind; ///< The kind of source code (parser) 16 | const char* url; ///< The location of the source code 17 | Nest_Node* mainNode; ///< The main node generated from this source code 18 | }; 19 | typedef struct Nest_SourceCode Nest_SourceCode; 20 | 21 | /// Function that is capable to parse the given source code 22 | void Nest_parseSourceCode(Nest_SourceCode* sourceCode, Nest_CompilationContext* ctx); 23 | 24 | /// Function that gets a specific line from the source code 25 | Nest_StringRef Nest_getSourceCodeLine(const Nest_SourceCode* sourceCode, int lineNum); 26 | 27 | /// Function that translates a node from CT to RT for the given source code 28 | Nest_Node* Nest_translateCtToRt(const Nest_SourceCode* sourceCode, Nest_Node* node); 29 | 30 | #ifdef __cplusplus 31 | } 32 | #endif 33 | -------------------------------------------------------------------------------- /src/Nest/Api/StringRef.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /// A reference to a string, or, range of characters 4 | struct Nest_StringRef { 5 | const char* begin; ///< The beginning of the string 6 | const char* end; ///< One past the last character of the string 7 | }; 8 | typedef struct Nest_StringRef Nest_StringRef; 9 | -------------------------------------------------------------------------------- /src/Nest/Api/TypeKindRegistrar.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "TypeRef.h" 4 | #include "EvalMode.h" 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | /// Type of function that changes the evaluation mode of a type 11 | typedef Nest_TypeRef (*FChangeTypeMode)(Nest_TypeRef, EvalMode); 12 | 13 | /// Registers a new type kind 14 | /// 15 | /// @param funChangeTypeMode The function used to change the mode of a type 16 | /// @return the ID of the new type kind 17 | int Nest_registerTypeKind(FChangeTypeMode funChangeTypeMode); 18 | 19 | /// Getter for the function that can change the type mode for the given type kind 20 | FChangeTypeMode Nest_getChangeTypeModeFun(int typeKind); 21 | 22 | //! Resets the registered type kinds 23 | void Nest_resetRegisteredTypeKinds(); 24 | 25 | #ifdef __cplusplus 26 | } 27 | #endif 28 | -------------------------------------------------------------------------------- /src/Nest/Api/TypeRef.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /// A type reference -- this is guaranteed to be unique for each type 4 | typedef const struct Nest_Type* Nest_TypeRef; 5 | -------------------------------------------------------------------------------- /src/Nest/Utils/Alloc.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifdef __cplusplus 4 | extern "C" { 5 | #endif 6 | 7 | typedef enum { 8 | allocGeneral, 9 | allocNode, 10 | allocType, 11 | allocString, 12 | 13 | numAllocBuckets 14 | } AllocBucket; 15 | 16 | /// Call this function to allocate some memory in the compiler. 17 | /// It tries to allocate in pages, therefore maximizing locality. 18 | void* alloc(unsigned int size, AllocBucket bucket); 19 | 20 | /// Returns a pointer that can hold up to the given amount of bytes, but does not 21 | /// mark the full region as occupied. Instead, the user should call endBuffer() 22 | /// to indicate the actual length of the buffer 23 | void* startBuffer(unsigned int size, AllocBucket bucket); 24 | /// Ends a buffer started with startBuffer() 25 | void endBuffer(unsigned int actualSize, AllocBucket bucket); 26 | 27 | /// Allocate memory for a string of the given length 28 | char* allocStr(unsigned int len); 29 | 30 | /// Duplicate the given string 31 | char* dupString(const char* str); 32 | 33 | /// Similar to startBuffer, but for strings 34 | char* startString(unsigned int maxLen); 35 | /// Similar to endBuffer, but for strings 36 | void endString(unsigned int actualLen); 37 | 38 | /// Cleans up all the allocated memory 39 | void cleanupMemory(); 40 | 41 | #ifdef __cplusplus 42 | } 43 | #endif 44 | -------------------------------------------------------------------------------- /src/Nest/Utils/Assert.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // Define a custom assert of MSVC compiler, use the standard assert for the rest 4 | #ifndef NDEBUG 5 | #if _MSC_VER > 1000 6 | #include 7 | #include 8 | #define ASSERT(expr) (void)( (!!(expr)) || ( (fprintf(stderr, "Assertion failed: %s, file %s, line %d\n", (#expr), __FILE__, __LINE__), _CrtDbgBreak(), 0) ) 9 | #define VERIFY ASSERT 10 | #else 11 | #include 12 | #define ASSERT(expr) assert(expr) 13 | #define VERIFY ASSERT 14 | #endif 15 | #else 16 | #define ASSERT(expr) \ 17 | if (1) \ 18 | ((void)0); \ 19 | else \ 20 | ((void)0) 21 | #define VERIFY(expr) (expr) 22 | #endif 23 | -------------------------------------------------------------------------------- /src/Nest/Utils/DiagnosticFormatter.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Diagnostic.h" 4 | #include "Nest/Api/Location.h" 5 | #include "Nest/Utils/cppif/Fwd.hpp" 6 | 7 | namespace Nest { 8 | /// Helper class that formats a diagnostic message 9 | /// Uses Boost::format to format the diagnostic message 10 | class DiagnosticFormatter { 11 | public: 12 | DiagnosticFormatter(Nest_DiagnosticSeverity severity, const char* fmt, bool dontThrow = false); 13 | DiagnosticFormatter(Nest_DiagnosticSeverity severity, const char* fmt, Location loc, 14 | bool dontThrow = false); 15 | 16 | /// Add a parameter to the diagnostic formatter 17 | template DiagnosticFormatter& operator%(const T& obj) { 18 | fmt_ % obj; 19 | return *this; 20 | } 21 | 22 | Nest_DiagnosticSeverity severity() const { return severity_; } 23 | std::string message() const { return fmt_.str(); } 24 | const Location& location() const { return location_; } 25 | bool dontThrow() const { return dontThrow_; } 26 | 27 | private: 28 | Nest_DiagnosticSeverity severity_; ///< The severity of the diagnostic to be reported 29 | boost::format fmt_; ///< The formatter object 30 | Location location_; ///< The location in the source code corresponding to this diagnostic 31 | bool dontThrow_; ///< If set, we won't throw an exception 32 | }; 33 | } // namespace Nest 34 | -------------------------------------------------------------------------------- /src/Nest/Utils/LocationUtils.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Nest/Api/Location.h" 4 | 5 | #ifdef __cplusplus 6 | extern "C" { 7 | #endif 8 | 9 | Nest_Location Nest_mkEmptyLocation(); 10 | Nest_Location Nest_mkLocation(const Nest_SourceCode* sourceCode, unsigned int startLineNo, 11 | unsigned int startColNo, unsigned int endLineNo, unsigned int endColNo); 12 | Nest_Location Nest_mkLocation1( 13 | const Nest_SourceCode* sourceCode, unsigned int lineNo, unsigned int colNo); 14 | 15 | /// Check if the given location is empty; true if it has no source code 16 | int Nest_isLocEmpty(const Nest_Location* loc); 17 | 18 | /// Compare two locations 19 | int Nest_compareLocations(const Nest_Location* loc1, const Nest_Location* loc2); 20 | 21 | #ifdef __cplusplus 22 | } 23 | #endif 24 | -------------------------------------------------------------------------------- /src/Nest/Utils/PrintTimer.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | namespace Nest { 6 | namespace Common { 7 | /// Helper timer that prints the elapsed time at the console 8 | /// 9 | /// In order for this to do something, the "enable" constructor parameter must be true; otherwise 10 | /// this has no effect. 11 | class PrintTimer { 12 | chrono::steady_clock::time_point startTime; 13 | const char* format; 14 | 15 | public: 16 | PrintTimer(bool enable, const char* startText, const char* fmtEnd = "[%d ms]\n") 17 | : format(enable ? fmtEnd : nullptr) { 18 | if (enable) { 19 | printf("%s", startText); 20 | startTime = chrono::steady_clock::now(); 21 | } 22 | } 23 | 24 | ~PrintTimer() { 25 | if (format) { 26 | auto durMs = chrono::duration_cast( 27 | chrono::steady_clock::now() - startTime); 28 | printf(format, durMs); 29 | } 30 | } 31 | 32 | PrintTimer(const PrintTimer&) = delete; 33 | PrintTimer(PrintTimer&&) = delete; 34 | const PrintTimer& operator=(const PrintTimer&) = delete; 35 | const PrintTimer& operator=(PrintTimer&&) = delete; 36 | }; 37 | } // namespace Common 38 | } // namespace Nest 39 | -------------------------------------------------------------------------------- /src/Nest/Utils/ProfilingFwd.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifndef SPARROW_PROFILING 4 | #define SPARROW_PROFILING 0 5 | #endif 6 | 7 | #if SPARROW_PROFILING 8 | 9 | //! Profiling type to store the source location data (from the compiler). 10 | //! Includes zone name, function name, filename, line number and color 11 | typedef struct ___tracy_source_location_data Nest_Profiling_LocType; 12 | 13 | #endif -------------------------------------------------------------------------------- /src/Nest/Utils/PtrArray.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "PtrRange.h" 4 | 5 | #ifdef __cplusplus 6 | extern "C" { 7 | #endif 8 | 9 | struct NestUtils_PtrArray { 10 | void** beginPtr; 11 | void** endPtr; 12 | void** endOfStorePtr; 13 | }; 14 | typedef struct NestUtils_PtrArray NestUtils_PtrArray; 15 | 16 | NestUtils_PtrArray NestUtils_emptyPtrArray(); 17 | NestUtils_PtrArray NestUtils_allocPtrArray(unsigned capacity); 18 | void NestUtils_freePtrArray(NestUtils_PtrArray arr); 19 | 20 | void NestUtils_reservePtrArray(NestUtils_PtrArray* arr, unsigned capacity); 21 | void NestUtils_resizePtrArray(NestUtils_PtrArray* arr, unsigned size); 22 | 23 | void NestUtils_appendObjectToPtrArray(NestUtils_PtrArray* arr, void* obj); 24 | void NestUtils_appendObjectsToPtrArray(NestUtils_PtrArray* arr, Nest_PtrRange objects); 25 | 26 | void NestUtils_insertObjectIntoPtrArray(NestUtils_PtrArray* arr, unsigned index, void* obj); 27 | void NestUtils_insertObjectsIntoPtrArray( 28 | NestUtils_PtrArray* arr, unsigned index, Nest_PtrRange objects); 29 | 30 | void NestUtils_eraseFromPtrArray(NestUtils_PtrArray* arr, unsigned index); 31 | 32 | #ifdef __cplusplus 33 | } 34 | #endif 35 | -------------------------------------------------------------------------------- /src/Nest/Utils/PtrRange.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | struct Nest_PtrRange { 4 | void** beginPtr; 5 | void** endPtr; 6 | }; 7 | typedef struct Nest_PtrRange Nest_PtrRange; 8 | -------------------------------------------------------------------------------- /src/Nest/Utils/cppif/CCLoc.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Nest/Utils/cppif/Fwd.hpp" 4 | 5 | namespace Nest { 6 | 7 | struct CCLoc { 8 | CompilationContext* context_; 9 | Location loc_; 10 | }; 11 | 12 | } // namespace Nest -------------------------------------------------------------------------------- /src/Nest/Utils/cppif/Fwd.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Nest/Api/EvalMode.h" 4 | 5 | struct Nest_Backend; 6 | struct Nest_CompilationContext; 7 | struct Nest_CompilerModule; 8 | struct Nest_Location; 9 | struct Nest_LocationPos; 10 | struct Nest_Modifier; 11 | struct Nest_ModifiersArray; 12 | struct Nest_Node; 13 | struct Nest_NodeArray; 14 | struct Nest_NodeProperties; 15 | struct Nest_NodeProperty; 16 | struct Nest_NodeRange; 17 | struct Nest_NodeRangeM; 18 | struct Nest_PtrRange; 19 | struct Nest_SourceCode; 20 | struct Nest_StringRef; 21 | struct Nest_SymTab; 22 | struct Nest_Type; 23 | using Nest_TypeRef = const struct Nest_Type*; 24 | 25 | namespace Nest { 26 | 27 | using CompilationContext = Nest_CompilationContext; 28 | using Location = Nest_Location; 29 | using Node = Nest_Node; 30 | using TypeRef = Nest_TypeRef; 31 | 32 | using EvalMode = Nest_EvalMode; 33 | 34 | struct StringRef; 35 | struct NodeHandle; 36 | struct NodeRange; 37 | struct NodeRangeM; 38 | 39 | } // namespace Nest 40 | -------------------------------------------------------------------------------- /src/Nest/Utils/cppif/TypeWithStorage.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Nest/Utils/cppif/Type.hpp" 4 | #include "Nest/Utils/cppif/NodeHandle.hpp" 5 | 6 | namespace Nest { 7 | 8 | /** 9 | * @brief Base class for all wrapper structs of types with storage. 10 | * 11 | * One cannot directly create objects of this type. Used derived classes. 12 | * 13 | * This doesn't expose any new functionality compared to base class Type. However, this is useful to 14 | * propagate the information that a type has storage (type safety). 15 | * 16 | * @see Type 17 | */ 18 | struct TypeWithStorage : Type { 19 | TypeWithStorage() = default; 20 | TypeWithStorage(Nest::TypeRef type); 21 | 22 | //!@{ Operations 23 | 24 | //! @copydoc Type::changeMode 25 | TypeWithStorage changeMode(Nest::EvalMode mode, Nest::Location loc = Nest::Location{}) const { 26 | return {Type::changeMode(mode, loc)}; 27 | } 28 | 29 | //!@} 30 | }; 31 | 32 | } // namespace Nest 33 | -------------------------------------------------------------------------------- /src/Nest/src/Api/Backend.c: -------------------------------------------------------------------------------- 1 | #include "Nest/Api/Backend.h" 2 | #include "Nest/Utils/Assert.h" 3 | 4 | static const int _maxBackends = 100; 5 | Nest_Backend* _allBackends[100]; 6 | unsigned int _numBackends = 0; 7 | 8 | int Nest_registerBackend(Nest_Backend* backend) { 9 | if (_numBackends >= _maxBackends) 10 | return -1; 11 | int idx = _numBackends++; 12 | _allBackends[idx] = backend; 13 | return idx; 14 | } 15 | 16 | int Nest_getNumBackends() { return _numBackends; } 17 | 18 | Nest_Backend* Nest_getBackend(int idx) { 19 | ASSERT(idx >= 0 && idx < _numBackends); 20 | return _allBackends[idx]; 21 | } 22 | 23 | void Nest_clearBackends() { _numBackends = 0; } 24 | -------------------------------------------------------------------------------- /src/Nest/src/Api/Nest.c: -------------------------------------------------------------------------------- 1 | #include "Nest/Api/Nest.h" 2 | #include "Nest/Api/CompilerModule.h" 3 | 4 | #include "Nest/Api/Backend.h" 5 | #include "Nest/Api/Type.h" 6 | #include "Nest/Api/TypeKindRegistrar.h" 7 | #include "Nest/Api/NodeKindRegistrar.h" 8 | #include "Nest/Api/SourceCodeKindRegistrar.h" 9 | #include "Nest/Api/Compiler.h" 10 | #include "Nest/Utils/Alloc.h" 11 | #include "Nest/Utils/Diagnostic.h" 12 | 13 | void Nest_initModule() { Nest_compilerInit(); } 14 | 15 | void Nest_destroyModule() { 16 | Nest_compilerDestroy(); 17 | Nest_clearBackends(); 18 | Nest_resetTypes(); 19 | Nest_resetRegisteredTypeKinds(); 20 | Nest_resetRegisteredNodeKinds(); 21 | Nest_resetRegisteredSourceCodeKinds(); 22 | Nest_resetDiagnostic(); 23 | 24 | // Cleanup all allocated memory 25 | cleanupMemory(); 26 | } 27 | 28 | static Nest_CompilerModule theNestModule = {"Nest", 29 | "The core of the compiler; defines the main services of the compiler, and the interactions " 30 | "between different components", 31 | "LucTeo", "www.lucteo.ro", 1, 0, &Nest_initModule, &Nest_destroyModule, 0}; 32 | 33 | Nest_CompilerModule* getNestModule() { return &theNestModule; } -------------------------------------------------------------------------------- /src/Nest/src/Api/NodeProperties.c: -------------------------------------------------------------------------------- 1 | #include "Nest/Api/NodeProperties.h" 2 | 3 | #include 4 | 5 | void Nest_addProperty(Nest_NodeProperties* properties, Nest_NodeProperty prop) { 6 | // Make sure we have enough space in our array 7 | unsigned curSize = properties->end - properties->begin; 8 | unsigned capacity = properties->endOfStore - properties->begin; 9 | if (capacity == 0) 10 | capacity = 8; // initial capacity 11 | while (capacity < curSize + 1) 12 | capacity += (capacity + 1) / 2; // growth factor: 1.5 13 | if (capacity > (properties->endOfStore - properties->begin)) { 14 | // Not enough space. Realloc the array 15 | unsigned curSize = properties->end - properties->begin; 16 | properties->begin = realloc(properties->begin, capacity * sizeof(Nest_NodeProperty)); 17 | properties->end = properties->begin + curSize; 18 | properties->endOfStore = properties->begin + capacity; 19 | } 20 | // Actually add the node 21 | properties->begin[curSize] = prop; 22 | properties->end++; 23 | } 24 | -------------------------------------------------------------------------------- /src/Nest/src/Api/SourceCode.c: -------------------------------------------------------------------------------- 1 | #include "Nest/Api/SourceCode.h" 2 | #include "Nest/Api/SourceCodeKindRegistrar.h" 3 | #include "Nest/Utils/Alloc.h" 4 | #include "Nest/Utils/Assert.h" 5 | 6 | void Nest_parseSourceCode(Nest_SourceCode* sourceCode, Nest_CompilationContext* ctx) { 7 | ASSERT(sourceCode); 8 | FParseSourceCode f = Nest_getParseSourceCodeFun(sourceCode->kind); 9 | if (f) 10 | f(sourceCode, ctx); 11 | } 12 | 13 | Nest_StringRef Nest_getSourceCodeLine(const Nest_SourceCode* sourceCode, int lineNum) { 14 | ASSERT(sourceCode); 15 | FGetSourceCodeLine f = Nest_getGetSourceCodeLineFun(sourceCode->kind); 16 | if (f) 17 | return f(sourceCode, lineNum); 18 | 19 | Nest_StringRef null = {0, 0}; 20 | return null; 21 | } 22 | 23 | Nest_Node* Nest_translateCtToRt(const Nest_SourceCode* sourceCode, Nest_Node* node) { 24 | ASSERT(sourceCode); 25 | FTranslateCtToRt f = Nest_getTranslateCtToRtFun(sourceCode->kind); 26 | if (f) 27 | return f(sourceCode, node); 28 | return node; 29 | } 30 | -------------------------------------------------------------------------------- /src/Nest/src/Api/TypeKindRegistrar.c: -------------------------------------------------------------------------------- 1 | #include "Nest/Api/TypeKindRegistrar.h" 2 | #include "Nest/Api/Type.h" 3 | #include "Nest/Utils/Assert.h" 4 | 5 | struct _TypeFunctions { 6 | FChangeTypeMode changeTypeMode; 7 | }; 8 | 9 | /// The registered type kinds 10 | struct _TypeFunctions _allTypeKinds[100]; 11 | unsigned int _numTypeKinds = 0; 12 | 13 | int Nest_registerTypeKind(FChangeTypeMode funChangeTypeMode) { 14 | int typeKindId = _numTypeKinds++; 15 | struct _TypeFunctions f = {funChangeTypeMode}; 16 | _allTypeKinds[typeKindId] = f; 17 | return typeKindId; 18 | } 19 | 20 | FChangeTypeMode Nest_getChangeTypeModeFun(int typeKind) { 21 | ASSERT(0 <= typeKind && typeKind < _numTypeKinds); 22 | return _allTypeKinds[typeKind].changeTypeMode; 23 | } 24 | 25 | void Nest_resetRegisteredTypeKinds() { _numTypeKinds = 0; } -------------------------------------------------------------------------------- /src/Nest/src/StdInc.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Nest/Utils/DefaultStdInc.hpp" 4 | -------------------------------------------------------------------------------- /src/Nest/src/Utils/DiagnosticFormatter.cpp: -------------------------------------------------------------------------------- 1 | #include "Nest/src/StdInc.hpp" 2 | #include "Nest/Utils/DiagnosticFormatter.hpp" 3 | 4 | using namespace Nest; 5 | 6 | DiagnosticFormatter::DiagnosticFormatter( 7 | Nest_DiagnosticSeverity severity, const char* fmt, bool dontThrow) 8 | : severity_(severity) 9 | , fmt_(fmt) 10 | , location_() 11 | , dontThrow_(dontThrow) {} 12 | 13 | DiagnosticFormatter::DiagnosticFormatter( 14 | Nest_DiagnosticSeverity severity, const char* fmt, Location loc, bool dontThrow) 15 | : severity_(severity) 16 | , fmt_(fmt) 17 | , location_(loc) 18 | , dontThrow_(dontThrow) {} 19 | -------------------------------------------------------------------------------- /src/Nest/src/Utils/Profiling.cpp: -------------------------------------------------------------------------------- 1 | #include "Nest/Utils/Profiling.h" 2 | 3 | #if SPARROW_PROFILING 4 | 5 | // Include TracyClient.cpp after defining TRACY_ENABLE 6 | #include "../../../externals/tracy/TracyClient.cpp" 7 | 8 | extern "C" const Nest_Profiling_LocType* Nest_Profiling_createLoc( 9 | const char* name, const char* function, const char* file, unsigned line, unsigned color) { 10 | Nest_Profiling_LocType* loc = (Nest_Profiling_LocType*)malloc(sizeof(Nest_Profiling_LocType)); 11 | loc->name = name; 12 | loc->function = function; 13 | loc->file = file; 14 | loc->line = line; 15 | loc->color = color; 16 | return loc; 17 | } 18 | 19 | #endif -------------------------------------------------------------------------------- /src/Nest/src/Utils/cppif/NodeRange.cpp: -------------------------------------------------------------------------------- 1 | #include "Nest/src/StdInc.hpp" 2 | #include "Nest/Utils/cppif/NodeRange.hpp" 3 | #include "Nest/Utils/Diagnostic.hpp" 4 | #include "Nest/Utils/cppif/StringRef.hpp" 5 | 6 | using Nest::NodeHandle; 7 | 8 | namespace Nest { 9 | 10 | vector NodeRange::toVec() const { return vector(begin(), end()); } 11 | 12 | const char* NodeRange::toString() const { 13 | ostringstream ss; 14 | ss << *this; 15 | return strdup(ss.str().c_str()); 16 | } 17 | 18 | vector NodeRangeM::toVec() const { return vector(begin(), end()); } 19 | 20 | const char* NodeRangeM::toString() const { return NodeRange(range).toString(); } 21 | 22 | ostream& operator<<(ostream& os, NodeRange r) { 23 | os << '['; 24 | bool first = true; 25 | for (auto node : r) { 26 | if (first) 27 | first = false; 28 | else 29 | os << ", "; 30 | if (node) 31 | os << node.toString(); 32 | else 33 | os << "null"; 34 | } 35 | os << ']'; 36 | return os; 37 | } 38 | 39 | } // namespace Nest 40 | -------------------------------------------------------------------------------- /src/Nest/src/Utils/cppif/Type.cpp: -------------------------------------------------------------------------------- 1 | #include "Nest/src/StdInc.hpp" 2 | #include "Nest/Utils/cppif/Type.hpp" 3 | #include "Nest/Utils/Diagnostic.hpp" 4 | #include "Nest/Utils/cppif/NodeHandle.hpp" 5 | 6 | namespace Nest { 7 | 8 | Nest::NodeHandle Type::referredNode() const { return type_->referredNode; } 9 | 10 | Type Type::changeMode(EvalMode mode, Location loc) const { 11 | if (mode == type_->mode) 12 | return *this; 13 | 14 | TypeRef resType = Nest_changeTypeMode(type_, mode); 15 | if (!resType) 16 | REP_INTERNAL(loc, "Don't know how to change eval mode of type %1%") % type_; 17 | ASSERT(resType); 18 | 19 | if (mode == modeCt && resType->mode != modeCt) 20 | REP_ERROR_RET(nullptr, loc, "Type '%1%' cannot be used at compile-time") % type_; 21 | 22 | return resType; 23 | } 24 | 25 | bool sameTypeIgnoreMode(Type t1, Type t2) { 26 | ASSERT(t1); 27 | ASSERT(t2); 28 | if (t1 == t2) 29 | return true; 30 | if (t1.kind() != t2.kind() || t1.mode() == t2.mode()) 31 | return false; 32 | auto t = t1.changeMode(t2.mode()); 33 | return t == t2; 34 | } 35 | 36 | ostream& operator<<(ostream& os, Type type) { return os << type.description(); } 37 | 38 | } // namespace Nest 39 | -------------------------------------------------------------------------------- /src/Nest/src/Utils/cppif/TypeWithStorage.cpp: -------------------------------------------------------------------------------- 1 | #include "Nest/src/StdInc.hpp" 2 | #include "Nest/Utils/cppif/TypeWithStorage.hpp" 3 | #include "Nest/Utils/Diagnostic.hpp" 4 | 5 | namespace Nest { 6 | 7 | TypeWithStorage::TypeWithStorage(TypeRef type) 8 | : Type(type) { 9 | if (type && !type->hasStorage) 10 | REP_INTERNAL(NOLOC, "TypeWithStorage constructed with non-storage type (%1%)") % type; 11 | } 12 | 13 | } // namespace Nest 14 | -------------------------------------------------------------------------------- /src/SparrowCompiler/AstDump.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | typedef struct Nest_Node Nest_Node; 4 | 5 | #ifdef __cplusplus 6 | extern "C" { 7 | #endif 8 | 9 | /** 10 | * \brief Dumps AST starting at the given node to a .json file 11 | * 12 | * This will create a .json file describing the AST tree starting with the given 13 | * node. We include children, referred nodes and properties of all the nodes. 14 | * 15 | * If a node is serialized once, it will not be serialized a second time into 16 | * the same dump. 17 | * 18 | * This will only dump the nodes in the same source code as the given node. 19 | * 20 | * @param node The start node to be dumped 21 | * @param filename The filename where to dump the AST 22 | */ 23 | void dumpAstNode(Nest_Node* node, const char* filename); 24 | 25 | #ifdef __cplusplus 26 | } 27 | #endif 28 | -------------------------------------------------------------------------------- /src/SparrowCompiler/Settings.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | bool initSettingsWithArgs(int argc, char** argv); 4 | -------------------------------------------------------------------------------- /src/SparrowCompiler/StdInc.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Nest/Utils/DefaultStdInc.hpp" 4 | #include "Nest/Utils/cppif/Fwd.hpp" 5 | -------------------------------------------------------------------------------- /src/SparrowCompiler/VersionInfo.h.in: -------------------------------------------------------------------------------- 1 | #define PLATFORM_NAME "${CMAKE_SYSTEM_NAME}" 2 | #define PLATFORM_VERSION "${CMAKE_SYSTEM_VERSION}" 3 | 4 | #define COMPILER_NAME "SparrowCompiler" 5 | #define COMPILER_VERSION "${SparrowCompiler_BUILD_VERSION}" 6 | #define COMPILER_VERSIONMAJOR ${SparrowCompiler_MAJOR_VERSION} 7 | #define COMPILER_VERSIONMINOR ${SparrowCompiler_MINOR_VERSION} 8 | 9 | #define COMPILER_BUILD_DATE "${SparrowCompiler_BUILD_DATE}" 10 | #define COMPILER_BUILD_YEAR ${SparrowCompiler_BUILD_YEAR} 11 | -------------------------------------------------------------------------------- /src/SparrowFrontend/CtApiFunctions.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | typedef struct Nest_Backend Nest_Backend; 4 | 5 | namespace SprFrontend { 6 | void registerCtApiFunctions(Nest_Backend* backend); 7 | } 8 | -------------------------------------------------------------------------------- /src/SparrowFrontend/Grammar/Parser.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace SprFrontend { 4 | struct ParserContext; 5 | struct CompilerErrorReporter; 6 | struct CompilerAstBuilder; 7 | 8 | /// The parser for the Sparrow source files 9 | class Parser { 10 | public: 11 | /// Constructs the Sparrow parser over the file indicated by the given source code 12 | Parser(Location loc); 13 | 14 | /// Constructs the Sparrow parser over the file indicated by the given source code, parsing the 15 | /// given string 16 | Parser(Location loc, StringRef code); 17 | 18 | ~Parser(); 19 | 20 | Node* parseModule(); 21 | Node* parseExpression(); 22 | 23 | private: 24 | //! The error reporter passed to the Sparrow parser code 25 | CompilerErrorReporter* errReporter_; 26 | //! The AST builder object passed to the Sparrow parser code 27 | CompilerAstBuilder* astBuilder_; 28 | //! The context of the Parser; used for interop with the code in Sparrow 29 | ParserContext* ctx_; 30 | }; 31 | } // namespace SprFrontend 32 | -------------------------------------------------------------------------------- /src/SparrowFrontend/Grammar/fileCharSource.spr: -------------------------------------------------------------------------------- 1 | import ext 2 | import os, std.ranges, std.string 3 | 4 | //! A char source that reads the content of a file 5 | datatype FileCharSource 6 | _file: File 7 | 8 | fun ctor(this: !FileCharSource, filename: StringRef) 9 | _file ctor filename 10 | 11 | fun isValid(this: !FileCharSource) = _file.isOpen 12 | 13 | fun readChars(this: !FileCharSource, dest: !String, numChars: Int) 14 | for i = 0..numChars 15 | var ch = _file.readChar 16 | if _file.isEof 17 | break 18 | dest += ch 19 | -------------------------------------------------------------------------------- /src/SparrowFrontend/Grammar/node.spr: -------------------------------------------------------------------------------- 1 | module sparrowc.spr.grammar.node 2 | 3 | /// A node in the compiler, expressing the root of an AST 4 | [bitcopiable] 5 | datatype Node = UntypedPtr 6 | 7 | fun isSet(n: Node): Bool = n.data.data !== null 8 | fun isNull(n: Node): Bool = n.data.data === null 9 | -------------------------------------------------------------------------------- /src/SparrowFrontend/Grammar/parserDefs.spr: -------------------------------------------------------------------------------- 1 | module sparrowc.spr.grammar.parserDefs 2 | 3 | import node 4 | import meta.location 5 | import std.tuple, std.string, std.vector 6 | 7 | /// A string (representing an identifier) and the corresponding location 8 | datatype LocString = Location*String 9 | 10 | /// Vector of LocString objects 11 | using LocStringVec = LocString Vector 12 | 13 | -------------------------------------------------------------------------------- /src/SparrowFrontend/Grammar/stringCharSource.spr: -------------------------------------------------------------------------------- 1 | import ext 2 | import std.ranges, std.string 3 | 4 | //! A char source that reads chars from a given StringRef 5 | [initCtor] 6 | datatype StringCharSource 7 | _content: StringRef 8 | 9 | fun readChars(this: !StringCharSource, dest: !String, numChars: Int) 10 | var sz: Int = _content.size 11 | var toRead = ife(numChars < sz, numChars, sz) 12 | for i = 0..sz 13 | dest += _content.front 14 | _content.popFront 15 | 16 | 17 | -------------------------------------------------------------------------------- /src/SparrowFrontend/Helpers/CommonCode.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace SprFrontend { 4 | /// Create a constructor call with any number of arguments 5 | Node* createCtorCall(const Location& loc, CompilationContext* context, Nest_NodeRange args); 6 | 7 | /// Create a constructor call with one argument 8 | Node* createCtorCall( 9 | const Location& loc, CompilationContext* context, Node* thisArg, Node* initArg); 10 | 11 | /// Create a destructor call 12 | Node* createDtorCall(const Location& loc, CompilationContext* context, Node* thisArg); 13 | 14 | /// Creates the code that calls the given function 15 | Node* createFunctionCall( 16 | const Location& loc, CompilationContext* context, Node* fun, Nest_NodeRange args); 17 | 18 | /// Create a temporary variable structure given the construct action for the given variable 19 | Node* createTempVarConstruct(const Location& loc, CompilationContext* context, 20 | Node* constructAction, Node* var, Node* varRef = nullptr); 21 | 22 | /// Create a temporary to be able to get a reference, out of a plain data-type node. 23 | /// I.e., used to get a "T const" value from a "T" compile-time value 24 | NodeHandle createTmpForRef(NodeHandle src, TypeWithStorage destType); 25 | 26 | /// Assuming the given node points to a function, creates a FunPtr object to refer to that function 27 | Node* createFunPtr(Node* funNode); 28 | } // namespace SprFrontend 29 | -------------------------------------------------------------------------------- /src/SparrowFrontend/Helpers/Ct.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "Nest/Api/EvalMode.h" 5 | 6 | #include 7 | 8 | namespace SprFrontend { 9 | /// Given two compile-time values, checks if they are equal (by using the '==' operator) 10 | bool ctValsEqual(Node* v1, Node* v2); 11 | 12 | StringRef getStringCtValue(Node* val); 13 | bool getBoolCtValue(Node* val); 14 | int getIntCtValue(Node* val); 15 | char* getByteRefCtValue(Node* val); 16 | } // namespace SprFrontend 17 | -------------------------------------------------------------------------------- /src/SparrowFrontend/Helpers/Impl/Intrinsics.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "Nest/Utils/cppif/NodeUtils.hpp" 5 | 6 | namespace Feather { 7 | struct FunctionDecl; 8 | } 9 | 10 | namespace SprFrontend { 11 | 12 | using Nest::NodeHandle; 13 | using Nest::NodeRange; 14 | 15 | /// Checks if the given function call is a basic intrinsic 16 | /// If yes, generates the appropriate code for it 17 | NodeHandle handleIntrinsic(Feather::FunctionDecl fun, CompilationContext* context, 18 | const Location& loc, NodeRange args); 19 | } // namespace SprFrontend 20 | -------------------------------------------------------------------------------- /src/SparrowFrontend/Helpers/QualifiedId.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "QualifiedId.h" 3 | 4 | #include "Feather/Utils/FeatherUtils.hpp" 5 | #include "Nest/Utils/cppif/NodeUtils.hpp" 6 | 7 | void SprFrontend::interpretQualifiedId(Node* n, QidVec& res) { 8 | ASSERT(n); 9 | if (n->nodeKind == nkSparrowExpIdentifier) { 10 | res.emplace_back(make_pair(Feather_getName(n), n->location)); 11 | } else if (n->nodeKind == nkSparrowExpCompoundExp) { 12 | Node* base = at(n->children, 0); 13 | interpretQualifiedId(base, res); 14 | res.emplace_back(make_pair(Feather_getName(n), n->location)); 15 | } else if (n->nodeKind == nkSparrowExpStarExp) { 16 | Node* base = at(n->children, 0); 17 | interpretQualifiedId(base, res); 18 | res.emplace_back(make_pair(StringRef{}, n->location)); 19 | } else 20 | REP_INTERNAL(n->location, "Don't know how to interpret node %1% in qualified id") % n; 21 | } 22 | -------------------------------------------------------------------------------- /src/SparrowFrontend/Helpers/QualifiedId.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include 6 | 7 | namespace SprFrontend { 8 | /// A QID: a list of names with the associated locations 9 | typedef vector> QidVec; 10 | 11 | /// Interprets a qualified id node; if the given node is a star expression, the last element on the 12 | /// result will be the empty string 13 | void interpretQualifiedId(Node* n, QidVec& res); 14 | } // namespace SprFrontend 15 | -------------------------------------------------------------------------------- /src/SparrowFrontend/Helpers/StdDef.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Nest/Utils/cppif/TypeWithStorage.hpp" 4 | 5 | namespace SprFrontend { 6 | namespace StdDef { 7 | 8 | using Nest::Type; 9 | using Nest::TypeWithStorage; 10 | 11 | extern TypeWithStorage typeType; 12 | extern Type typeVoid; 13 | extern TypeWithStorage typeNull; 14 | extern TypeWithStorage typeBool; 15 | extern TypeWithStorage typeByte; 16 | extern TypeWithStorage typeInt; 17 | extern TypeWithStorage typeStringRef; 18 | 19 | extern TypeWithStorage typeRefType; 20 | extern TypeWithStorage typeRefByte; 21 | extern TypeWithStorage typeRefInt; 22 | 23 | extern Node* clsType; 24 | extern Node* clsNull; 25 | extern Node* clsBool; 26 | 27 | extern Node* opRefEq; 28 | extern Node* opRefNe; 29 | } // namespace StdDef 30 | 31 | /// Creates the Type class & corresponding type; we need it before loading anything else 32 | void initTypeType(CompilationContext* ctx); 33 | 34 | void checkStdClass(Node* cls); 35 | void checkStdFunction(Node* cls); 36 | } // namespace SprFrontend 37 | -------------------------------------------------------------------------------- /src/SparrowFrontend/IntMods.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | typedef struct Nest_Modifier Nest_Modifier; 4 | 5 | Nest_Modifier* SprFe_getClassMembersIntMod(); 6 | Nest_Modifier* SprFe_getCtorMembersIntMod(); 7 | Nest_Modifier* SprFe_getDtorMembersIntMod(); 8 | -------------------------------------------------------------------------------- /src/SparrowFrontend/Mods.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Nest/Api/StringRef.h" 4 | 5 | typedef struct Nest_Modifier Nest_Modifier; 6 | 7 | Nest_Modifier* SprFe_getPublicMod(); 8 | Nest_Modifier* SprFe_getProtectedMod(); 9 | Nest_Modifier* SprFe_getPrivateMod(); 10 | Nest_Modifier* SprFe_getCtMod(); 11 | Nest_Modifier* SprFe_getRtMod(); 12 | Nest_Modifier* SprFe_getAutoCtMod(); 13 | Nest_Modifier* SprFe_getCtGenericMod(); 14 | Nest_Modifier* SprFe_getNativeMod(StringRef name); 15 | Nest_Modifier* SprFe_getConvertMod(); 16 | Nest_Modifier* SprFe_getNoDefaultMod(); 17 | Nest_Modifier* SprFe_getInitCtorMod(); 18 | Nest_Modifier* SprFe_getBitCopiableMod(); 19 | Nest_Modifier* SprFe_getAutoBitCopiableMod(); 20 | Nest_Modifier* SprFe_getMacroMod(); 21 | Nest_Modifier* SprFe_getNoInlineMod(); 22 | 23 | bool SprFe_isEvalModeMod(Nest_Modifier* mod); -------------------------------------------------------------------------------- /src/SparrowFrontend/NodeCommonsCpp.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "NodeCommonsH.h" 4 | 5 | #include "Nest/Utils/Diagnostic.hpp" 6 | #include "Nest/Utils/cppif/StringRef.hpp" 7 | #include "Nest/Api/CompilationContext.h" 8 | #include "Nest/Api/Type.h" 9 | #include "Nest/Api/SymTab.h" 10 | 11 | #include 12 | #include 13 | #include "Feather/Api/Feather.h" 14 | #include "Feather/Utils/FeatherUtils.hpp" 15 | 16 | namespace SprFrontend {}; 17 | 18 | using namespace SprFrontend; 19 | -------------------------------------------------------------------------------- /src/SparrowFrontend/NodeCommonsH.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Nest/Api/SymTab.h" 4 | #include "Nest/Api/Type.h" 5 | #include "Nest/Api/Node.h" 6 | 7 | #include "Nodes/SparrowNodes.h" 8 | #include "Nest/Utils/cppif/NodeHandle.hpp" 9 | #include "Nest/Utils/cppif/NodeRange.hpp" 10 | #include "Nest/Utils/cppif/TypeWithStorage.hpp" 11 | #include "Nest/Utils/cppif/CCLoc.hpp" 12 | 13 | namespace SprFrontend { 14 | 15 | using Nest::CCLoc; 16 | using Nest::CompilationContext; 17 | using Nest::Location; 18 | using Nest::Node; 19 | using Nest::NodeHandle; 20 | using Nest::NodeRange; 21 | using Nest::Range; 22 | using Nest::StringRef; 23 | using Nest::Type; 24 | using Nest::TypeWithStorage; 25 | 26 | } // namespace SprFrontend -------------------------------------------------------------------------------- /src/SparrowFrontend/Nodes/AccessType.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace SprFrontend { 4 | /// The type of access for declarations 5 | enum AccessType { 6 | unspecifiedAccess = 0, //!< Unspecified; we just take the default or the parent's access type 7 | publicAccess, //!< Declaration is visible by anyone; it will be made accessible with 'using' 8 | protectedAccess, //!< It is not be 'transported' by 'using', but it can be access with alternate 9 | //!< means (e.g., operator call) by anybody 10 | privateAccess, //!< It will only be accessible for the current module 11 | }; 12 | 13 | inline const char* accessTypeToString(AccessType accessType) { 14 | switch (accessType) { 15 | case publicAccess: 16 | return "public"; 17 | case protectedAccess: 18 | return "protected"; 19 | case privateAccess: 20 | return "private"; 21 | case unspecifiedAccess: 22 | default: 23 | return "unspecified"; 24 | } 25 | } 26 | } // namespace SprFrontend 27 | -------------------------------------------------------------------------------- /src/SparrowFrontend/Nodes/SprProperties.cpp: -------------------------------------------------------------------------------- 1 | #include "SprProperties.h" 2 | 3 | const char* SprFrontend::propConvert = "spr.convert"; 4 | const char* SprFrontend::propTempVarContstruction = "spr.tempVarConstruction"; 5 | const char* SprFrontend::propNoDefault = "spr.noDefault"; 6 | const char* SprFrontend::propCtGeneric = "spr.ctGeneric"; 7 | const char* SprFrontend::propGenerateInitCtor = "spr.generateInitCtor"; 8 | const char* SprFrontend::propMacro = "spr.macro"; 9 | const char* SprFrontend::propAllowDeclExp = "spr.allowDeclExp"; 10 | const char* SprFrontend::propNoWarnIfNoDeclFound = "spr.noWarnIfNoDeclFound"; 11 | const char* SprFrontend::propThisParamIdx = "spr.thisParamIdx"; 12 | const char* SprFrontend::propThisParamType = "spr.thisParamType"; 13 | const char* SprFrontend::propOverloadPrio = "spr.overloadPrio"; 14 | -------------------------------------------------------------------------------- /src/SparrowFrontend/Nodes/SprProperties.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Feather/Utils/FeatherUtils.h" 4 | 5 | namespace SprFrontend { 6 | extern const char* propConvert; 7 | extern const char* propTempVarContstruction; 8 | extern const char* propNoDefault; 9 | extern const char* propCtGeneric; 10 | extern const char* propGenerateInitCtor; 11 | extern const char* propMacro; 12 | extern const char* propAllowDeclExp; 13 | extern const char* propNoWarnIfNoDeclFound; 14 | extern const char* propThisParamIdx; 15 | extern const char* propThisParamType; 16 | extern const char* propOverloadPrio; 17 | 18 | constexpr const char* propVarInit = "spr.varInit"; 19 | constexpr const char* propSprGivenType = "spr.givenType"; 20 | constexpr const char* propSprOrigCat = "spr.origCat"; 21 | constexpr const char* propSprLiteralType = "spr.literalType"; 22 | constexpr const char* propSprLiteralData = "spr.literalData"; 23 | constexpr const char* propSprOperation = "spr.operation"; 24 | constexpr const char* propBitCopiable = "spr.bitcopiable"; 25 | constexpr const char* propAutoBitCopiable = "spr.autoBitcopiable"; 26 | constexpr const char* propNoAutoConst = "spr.noAutoConst"; 27 | } // namespace SprFrontend 28 | -------------------------------------------------------------------------------- /src/SparrowFrontend/Services/Callable/CallableServiceImpl.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "SparrowFrontend/NodeCommonsH.h" 4 | #include "SparrowFrontend/Services/ICallableService.h" 5 | 6 | namespace SprFrontend { 7 | 8 | struct CallableServiceImpl : ICallableService { 9 | //! @copydoc ICallableService::getCallables() 10 | Callables getCallables(NodeRange decls, EvalMode evalMode, 11 | const std::function& pred = {}, 12 | const char* ctorName = "ctor") override; 13 | }; 14 | 15 | //! The callable service instance that we are using across the Sparrow compiler 16 | extern unique_ptr g_CallableService; 17 | 18 | } // namespace SprFrontend 19 | -------------------------------------------------------------------------------- /src/SparrowFrontend/Services/Callable/Callables.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "SparrowFrontend/Services/Callable/Callables.h" 3 | #include "SparrowFrontend/Services/Callable/Callable.h" 4 | 5 | namespace SprFrontend { 6 | Callables::~Callables() { 7 | for (auto c : callables_) 8 | delete c; 9 | } 10 | } // namespace SprFrontend -------------------------------------------------------------------------------- /src/SparrowFrontend/Services/Callable/Callables.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "SparrowFrontend/NodeCommonsH.h" 4 | 5 | namespace SprFrontend { 6 | 7 | class Callable; 8 | 9 | //! A vector of callables. 10 | //! Provides deletion destructor; otherwise just a simple vector 11 | struct Callables { 12 | using _VecType = vector; 13 | using value_type = _VecType::value_type; 14 | using iterator = _VecType::iterator; 15 | using const_iterator = _VecType::const_iterator; 16 | 17 | Callables() {} 18 | ~Callables(); 19 | 20 | iterator begin() { return callables_.begin(); } 21 | iterator end() { return callables_.end(); } 22 | const_iterator begin() const { return callables_.begin(); } 23 | const_iterator end() const { return callables_.end(); } 24 | 25 | bool empty() const { return callables_.empty(); } 26 | int size() const { return int(callables_.size()); } 27 | Callable* operator[](int idx) { return callables_[idx]; } 28 | const Callable* operator[](int idx) const { return callables_[idx]; } 29 | 30 | vector callables_; 31 | }; 32 | 33 | } // namespace SprFrontend 34 | -------------------------------------------------------------------------------- /src/SparrowFrontend/Services/Concepts/ConceptsServiceImpl.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "SparrowFrontend/NodeCommonsH.h" 4 | #include "SparrowFrontend/Services/IConceptsService.h" 5 | 6 | namespace SprFrontend { 7 | 8 | //! The Sparrow implementation of the concepts service 9 | struct ConceptsServiceImpl : IConceptsService { 10 | bool conceptIsFulfilled(ConceptDecl concept, Type type) final; 11 | bool typeGeneratedFromGeneric(GenericDatatype genericDatatype, Type type) final; 12 | ConceptType baseConceptType(ConceptDecl concept) final; 13 | }; 14 | 15 | } // namespace SprFrontend 16 | -------------------------------------------------------------------------------- /src/SparrowFrontend/Services/ICallableService.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "SparrowFrontend/NodeCommonsH.h" 4 | #include "SparrowFrontend/Services/IConvertService.h" 5 | #include "SparrowFrontend/Services/Callable/Callables.h" 6 | 7 | #include "Feather/Utils/cppif/FeatherNodes.hpp" 8 | 9 | namespace SprFrontend { 10 | 11 | struct ICallableService { 12 | virtual ~ICallableService() {} 13 | 14 | //! Given some declarations, try to gets a list of Callable objects from it. 15 | //! Returns an empty list if the declarations are not callable 16 | //! We apply the given predicate to filter out decls we don't want. 17 | virtual Callables getCallables(NodeRange decls, EvalMode evalMode, 18 | const std::function& pred = {}, const char* ctorName = "ctor") = 0; 19 | }; 20 | 21 | //! The callable service instance that we are using across the Sparrow compiler 22 | extern unique_ptr g_CallableService; 23 | 24 | } // namespace SprFrontend 25 | -------------------------------------------------------------------------------- /src/SparrowFrontend/Services/IConceptsService.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "SparrowFrontend/NodeCommonsH.h" 4 | #include "SparrowFrontend/Nodes/Decl.hpp" 5 | #include "SparrowFrontend/Nodes/Generics.hpp" 6 | 7 | namespace SprFrontend { 8 | 9 | //! The interface for the service that deals with checking concepts. 10 | //! Used so that we can easily mock and replace this service. 11 | struct IConceptsService { 12 | virtual ~IConceptsService() {} 13 | 14 | //! Check if the given concept is fulfilled by the given type 15 | virtual bool conceptIsFulfilled(ConceptDecl concept, Type type) = 0; 16 | //! Check if the given type was generated from the given generic 17 | //! This will make generics behave like concepts 18 | virtual bool typeGeneratedFromGeneric(GenericDatatype genericDatatype, Type type) = 0; 19 | 20 | //! Get the base concept type 21 | virtual ConceptType baseConceptType(ConceptDecl concept) = 0; 22 | }; 23 | 24 | //! The convert service instance that we are using across the Sparrow compiler 25 | extern unique_ptr g_ConceptsService; 26 | 27 | } // namespace SprFrontend -------------------------------------------------------------------------------- /src/SparrowFrontend/Services/IConvertService.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Convert/ConversionResult.h" 4 | 5 | namespace SprFrontend { 6 | 7 | //! Flags used when checking the conversion to alter the scope of the conversion 8 | enum ConversionFlags { 9 | flagsDefault = 0, 10 | flagDontCallConversionCtor = 1, 11 | }; 12 | 13 | //! The interface for the service that deals with conversions between types. 14 | //! Used so that we can easily mock and replace this service 15 | struct IConvertService { 16 | virtual ~IConvertService() {} 17 | 18 | //! Check if we can convert the source type to the destination type. 19 | //! The returned object can be used to apply the conversion to nodes of the source type. 20 | virtual ConversionResult checkConversion(CompilationContext* context, Type srcType, 21 | Type destType, ConversionFlags flags = flagsDefault) = 0; 22 | 23 | //! Checks if an "argument" node can be converted to a given type 24 | virtual ConversionResult checkConversion( 25 | Node* arg, Type destType, ConversionFlags flags = flagsDefault) = 0; 26 | }; 27 | 28 | //! The convert service instance that we are using across the Sparrow compiler 29 | extern unique_ptr g_ConvertService; 30 | 31 | } // namespace SprFrontend -------------------------------------------------------------------------------- /src/SparrowFrontend/Services/Overload/OverloadServiceImpl.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "SparrowFrontend/NodeCommonsH.h" 4 | #include "SparrowFrontend/Services/IOverloadService.h" 5 | 6 | namespace SprFrontend { 7 | 8 | //! The Sparrow implementation of the overload service 9 | struct OverloadServiceImpl : IOverloadService { 10 | Node* selectOverload(CompilationContext* context, const Location& loc, EvalMode evalMode, 11 | Nest_NodeRange decls, Nest_NodeRange args, OverloadReporting errReporting, 12 | StringRef funName) final; 13 | 14 | bool selectConversionCtor( 15 | CompilationContext* context, Node* destClass, EvalMode destMode, Type argType) final; 16 | 17 | Node* selectCtToRtCtor(Node* ctArg) final; 18 | }; 19 | 20 | } // namespace SprFrontend 21 | -------------------------------------------------------------------------------- /src/SparrowFrontend/SparrowFrontend.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | typedef struct Nest_CompilerModule Nest_CompilerModule; 4 | 5 | //! Getter for the SparrowFrontend module 6 | Nest_CompilerModule* getSparrowFrontendModule(); 7 | -------------------------------------------------------------------------------- /src/SparrowFrontend/SparrowSourceCode.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /// The kind of the Sparrow source code 4 | extern int SprFe_kindSparrowSourceCode; 5 | 6 | /// Register the Sparrow source code 7 | void SprFe_registerSparrowSourceCode(); 8 | 9 | /// Parses a Sparrow expression 10 | Node* SprFe_parseSparrowExpression(Location loc, const char* code); 11 | -------------------------------------------------------------------------------- /src/SparrowFrontend/StdInc.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Nest/Utils/DefaultStdInc.hpp" 4 | 5 | #include "Nest/Api/Compiler.h" 6 | #include "Nest/Api/Location.h" 7 | #include "Nest/Api/Type.h" 8 | #include "Nest/Utils/cppif/Fwd.hpp" 9 | #include "Nest/Utils/cppif/NodeUtils.hpp" 10 | 11 | // Common functions, exposed 12 | 13 | // TODO: remove these 14 | using Nest::all; 15 | using Nest::allM; 16 | using Nest::at; 17 | using Nest::begin; 18 | using Nest::end; 19 | using Nest::fromIniList; 20 | using Nest::size; 21 | 22 | // To speed up the compilation of the nodes 23 | #include "NodeCommonsCpp.h" -------------------------------------------------------------------------------- /src/SparrowFrontend/UserDefinedSourceCode.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | /// Register a UserDefined source code, for the given extension and name of the function called to 4 | /// handle the source code 5 | int SprFe_registerUserDefinedSourceCode(const char* ext, const char* funName); 6 | -------------------------------------------------------------------------------- /tests/Basic/Auto.spr: -------------------------------------------------------------------------------- 1 | //!! -t "SparrowImplicitLib.spr" -fno-main 2 | 3 | // Test purpose: Test AnyType as parameter 4 | 5 | // Takes a non-reference as a parameter 6 | fun f1(x: AnyType) if typeOf(x) == Int 7 | writeLn('non-ref') 8 | //x = 10 9 | 10 | // Takes a reference as a parameter 11 | fun f2(x: !AnyType) if typeOf(x) == !Int 12 | writeLn('ref') 13 | x = 20 14 | 15 | [native("test")] fun test(n: Int) 16 | var a: Int = 5 17 | 18 | f1(a) 19 | writeLn(a) 20 | f2(a) 21 | writeLn(a) 22 | 23 | /*<<>>*/ -------------------------------------------------------------------------------- /tests/Basic/Basic.spr: -------------------------------------------------------------------------------- 1 | //!! -t "SparrowImplicitLib.spr" -fno-main 2 | 3 | // Test purpose: Basic test with just a few operations 4 | 5 | fun factorial(n: Int): Int 6 | if ( equal(n, 0) ) 7 | return 1 8 | else 9 | return mul(n, factorial(sub(n,1))) 10 | 11 | [native("test")] 12 | fun test(n: Int) 13 | writeLnInt(15) 14 | writeLnInt(factorial(5)) 15 | 16 | /*<<>>*/ -------------------------------------------------------------------------------- /tests/Basic/CompDefines.spr: -------------------------------------------------------------------------------- 1 | //!! -t "SparrowImplicitLib.spr" -fno-main -D DEBUG -D "VAL=2+2" 2 | 3 | [native("test")] fun test(n: Int) 4 | if ( DEBUG ) 5 | writeLn("debug mode") 6 | else 7 | writeLn("release mode") 8 | writeLnInt(VAL) 9 | 10 | /*<<>>*/ -------------------------------------------------------------------------------- /tests/Basic/Compound.spr: -------------------------------------------------------------------------------- 1 | //!! -t "SparrowImplicitLib.spr" -fno-main 2 | 3 | datatype MyObj 4 | a: Int 5 | using st = 103 6 | 7 | fun ctor(this: !MyObj, i: Int) { a = i; } 8 | fun ctor(this: !MyObj, other: MyObj) { a = other.a; } 9 | 10 | fun print(this: MyObj) { write("MyObj: "); writeLn(a); } 11 | 12 | var go = MyObj(10) 13 | 14 | fun f1(): MyObj 15 | return MyObj(13); 16 | 17 | fun f2(): @MyObj 18 | return go mutToPtr; 19 | 20 | [native("test")] fun test(n: Int) 21 | writeLn(go.a) 22 | go.print() 23 | writeLn(go.st) 24 | writeLn("---") 25 | 26 | let o = MyObj(1) 27 | writeLn(o.a) 28 | o.print() 29 | writeLn(o.st) 30 | writeLn("---") 31 | 32 | writeLn(f1().a) 33 | f1().print() 34 | writeLn(f1().st) 35 | writeLn("---") 36 | 37 | writeLn(f2().a) 38 | f2().print() 39 | writeLn(f2().st) 40 | 41 | /*<<>>*/ -------------------------------------------------------------------------------- /tests/Basic/CtFactorial.spr: -------------------------------------------------------------------------------- 1 | //!! -t "SparrowImplicitLib.spr" -fno-main 2 | 3 | [autoCt] fun fact(n: Int): Int 4 | if ( n == 0 ) 5 | return 1; 6 | else 7 | return n* fact(n-1); 8 | 9 | fun testFact() 10 | let n = 5 11 | writeLn(fact(n)) 12 | writeLn(fact(5)) 13 | 14 | [native("test")] fun test(n: Int) 15 | testFact(); 16 | 17 | /*<<>>*/ -------------------------------------------------------------------------------- /tests/Basic/CtIf.spr: -------------------------------------------------------------------------------- 1 | //!! -t "SparrowImplicitLib.spr" -fno-main 2 | 3 | [native("writeLnFloat64"), autoCt] fun writeLnFloatCt(x: Float) 4 | 5 | // Function that can be called only with compile-time arguments 6 | [ct] fun ctTest(x: Float) 7 | writeLnFloatCt(x) 8 | 9 | [ct] if ( true ) 10 | fun my_f { writeLn("f.1"); } 11 | else 12 | fun my_f { writeLn("f.2"); } 13 | 14 | [ct] if ( false ) 15 | fun my_g { writeLn("g.1"); } 16 | else 17 | fun my_g { writeLn("g.2"); } 18 | 19 | [native("test")] fun test(n: Int) 20 | if ( true ) 21 | ctTest(1.0) 22 | else 23 | ctTest(2.0) 24 | 25 | [ct] if ( true ) 26 | ctTest(11.0) 27 | else 28 | ctTest(12.0) 29 | [ct] if ( false ) 30 | ctTest(21.0) 31 | else 32 | ctTest(22.0) 33 | 34 | [ct] if ( true ) 35 | writeLn("ok") 36 | else 37 | writeLn("fail") 38 | some error here 39 | 40 | my_f() 41 | my_g() 42 | 43 | /*<<>>*/ -------------------------------------------------------------------------------- /tests/Basic/CtToRt.spr: -------------------------------------------------------------------------------- 1 | //!! -t "SparrowImplicitLib.spr" -fno-main 2 | 3 | [ct] let t: Type = Int 4 | [ct] let u: Type 5 | 6 | [ct] let x: Int = 1 7 | [ct] let y: t = 2 8 | let z = 3 9 | 10 | [ct] var v: Int = 1 11 | 12 | [ct] let c1: Int@ = v mutToPtr 13 | 14 | [ct] fun testCt(a: Int) 15 | { 16 | } 17 | 18 | [autoCt] fun id(x: Int@): Int@ 19 | return x; 20 | 21 | fun printRef(x: Int@) 22 | writeLn(x); 23 | 24 | [native("test")] fun test(n: Int) 25 | testCt(x) 26 | testCt(y) 27 | //testCt(z); // Should raise an error 28 | 29 | writeLn(x) 30 | writeLn(y) 31 | writeLn(z) 32 | 33 | writeLn(c1) 34 | writeLn(id(c1)) 35 | writeLn(id(id(id(id(c1))))) 36 | //printRef(id(c1)); // Should raise an error 37 | 38 | /*<<>>*/ -------------------------------------------------------------------------------- /tests/Basic/CtToRtComplex.spr: -------------------------------------------------------------------------------- 1 | //!! -t "SparrowImplicitLib.spr" -fno-main 2 | 3 | datatype Pair 4 | x, y: Int; 5 | 6 | fun ctor(this: !Pair, x,y: Int) 7 | this.x = x 8 | this.y = y 9 | 10 | datatype Pair2 11 | x, y: Int; 12 | 13 | fun ctor(this: !Pair2, x,y: Int) 14 | this.x = x 15 | this.y = y 16 | 17 | fun ctorFromCt(this: !Pair2, src: Pair2 ct) 18 | writeLn("Pair2 Ct ctor") 19 | x ctor src.x 20 | y ctor src.y 21 | 22 | fun identity(obj: AnyType) = obj 23 | 24 | fun print(p: Pair) 25 | write("Pair{"); write(p.x); write(", "); write(p.y); writeLn("}"); 26 | fun print(p: Pair2) 27 | write("Pair2{"); write(p.x); write(", "); write(p.y); writeLn("}"); 28 | 29 | [native("test")] fun test(n: Int) 30 | let a = 101 31 | let b = 103 32 | [ct] let ca = 121 33 | [ct] let cb = 123 34 | 35 | let p1 = Pair(11,13) 36 | [ct] let p2 = Pair(21, 23) 37 | print(p1) 38 | print(p2) 39 | writeLn("---") 40 | 41 | let pp1 = Pair2(a,b) 42 | [ct] let pp2 = Pair2(ca, cb) 43 | print(pp1) 44 | print(pp2) 45 | writeLn("---") 46 | 47 | let pp3 = pp2 48 | print(pp3) 49 | let pp4 = identity(pp2) 50 | print(pp4) 51 | 52 | /*<<>>*/ -------------------------------------------------------------------------------- /tests/Basic/CtToRtErr.spr: -------------------------------------------------------------------------------- 1 | //!! -t "SparrowImplicitLib.spr" -fno-main 2 | 3 | [ct] let t: Type = Int 4 | [ct] let u: Type 5 | 6 | [ct] let x: Int = 1 7 | [ct] let y: t = 2 8 | let z = 3 9 | 10 | [ct] var v: Int = 1 11 | 12 | [ct] let c1: Int@ = v mutToPtr 13 | 14 | [ct] fun testCt(a: Int) 15 | { 16 | } 17 | 18 | [autoCt] fun id(x: Int@): Int@ 19 | return x; 20 | 21 | fun printRef(x: Int@) 22 | writeLn(x); 23 | 24 | [native("test")] fun test(n: Int) 25 | testCt(x) 26 | testCt(y) 27 | testCt(z) // ERROR 28 | 29 | writeLn(x) 30 | writeLn(y) 31 | writeLn(z) 32 | 33 | writeLn(c1) 34 | writeLn(id(c1)) 35 | writeLn(id(id(id(id(c1))))) 36 | printRef(id(c1)) // ERROR 37 | -------------------------------------------------------------------------------- /tests/Basic/CtorDtor.spr: -------------------------------------------------------------------------------- 1 | //!! -t "SparrowImplicitLib.spr" -fno-main -fno-rvo 2 | 3 | datatype MyType 4 | x: Int; 5 | 6 | fun ctor(this: !MyType) 7 | x = 0 8 | write('c'); write('t'); write('o'); write('r'); write('('); writeLn(')') 9 | fun ctor(this: !MyType, i: Int) 10 | x = i 11 | write('c'); write('t'); write('o'); write('r'); write('('); write(i); writeLn(')') 12 | fun ctor(this: !MyType, other: MyType) 13 | x = other.x 14 | write('c'); write('t'); write('o'); write('r'); write('('); write('C'); write(' '); write(x); writeLn(')') 15 | 16 | fun dtor(this: !MyType) 17 | write('d'); write('t'); write('o'); write('r'); write('-'); writeLn(x); 18 | 19 | let g: MyType = 999 20 | 21 | package TestPkg 22 | let g2: MyType = 777; 23 | 24 | fun doTest() 25 | let o1: MyType 26 | let o2: MyType = 1 27 | MyType(10) 28 | MyType(o2) 29 | let o3 = o1 30 | let o4 = MyType(100) 31 | write('o'); writeLn('k') 32 | 33 | [native("test")] fun test(n: Int) 34 | write('<'); writeLn('-') 35 | doTest() 36 | write('-'); writeLn('>') 37 | 38 | /*<< 58 | dtor-777 59 | dtor-999 60 | >>>*/ -------------------------------------------------------------------------------- /tests/Basic/Functor.spr: -------------------------------------------------------------------------------- 1 | //!! -t "SparrowImplicitLib.spr" -fno-main 2 | 3 | datatype Test 4 | ; 5 | 6 | fun ()(this: Test) 7 | writeLn("call operator"); 8 | 9 | fun ()(this: Test, x: Int) 10 | write("call operator(") 11 | write(x) 12 | writeLn(")") 13 | 14 | fun ()(this: Test, x,y: Int) 15 | write("call operator(") 16 | write(x) 17 | write(", ") 18 | write(y) 19 | writeLn(")") 20 | 21 | fun selfCall(this: Test) 22 | this(100); 23 | 24 | [native("test")] fun test(n: Int) 25 | let t: Test 26 | t() 27 | t(10) 28 | t(10, 20) 29 | writeLn("---") 30 | t.selfCall() 31 | 32 | /*<<>>*/ -------------------------------------------------------------------------------- /tests/Basic/ImplicitFunCall.spr: -------------------------------------------------------------------------------- 1 | //!! -t "SparrowImplicitLib.spr" -fno-main 2 | 3 | datatype Foo 4 | a: Int 5 | b: Int 6 | 7 | fun f(this: Foo): Foo { writeLn("inside Foo.f()"); return this; } 8 | 9 | fun g(this: Foo): Foo { writeLn("inside Foo.g()"); return this; } 10 | fun g(this: Foo, i: Int): Foo { writeLn("inside Foo.g(i)"); return this; } 11 | 12 | fun h(this: Foo, i: Int): Foo { writeLn("inside Foo.h(i)"); return this; } 13 | 14 | fun aa(this: Foo) = a 15 | 16 | fun f1 { writeLn("inside f1()"); } 17 | fun f2(i: Int) { writeLn("inside f2()"); } 18 | 19 | [native("test")] fun test(n: Int) 20 | f1 // inside f1() 21 | //f2; 22 | 23 | writeLn("---") 24 | 25 | let foo: Foo 26 | 27 | foo.a 28 | foo.b 29 | foo.f // inside Foo.f() 30 | //foo.g; 31 | //foo.h; 32 | writeLn("---") 33 | foo.f g // inside Foo.f() + inside Foo.g() 34 | writeLn(foo.aa + 13) // 13 35 | writeLn((foo.f aa) + 13) // inside Foo.f() + 13 36 | 37 | /*<<>>*/ -------------------------------------------------------------------------------- /tests/Basic/SameName.spr: -------------------------------------------------------------------------------- 1 | //!! -t "SparrowImplicitLib.spr" -fno-main 2 | 3 | datatype myName 4 | x: Int; 5 | 6 | fun ctor(this: !myName, x: Int) // ERROR ERROR 7 | this.x = x; 8 | 9 | fun myName = 10 10 | fun myName(x: Int) = x 11 | fun myName(x,y: Int) = x+y 12 | 13 | [native("test")] fun test(n: Int) 14 | let y: myName = 5 // E RROR 15 | writeLn(y.x) // E RROR 16 | let myName = 7 17 | writeLn(myName) 18 | writeLn(myName()) // E RROR 19 | writeLn(myName(15)) // E RROR 20 | writeLn(myName(15, 5)) // E RROR 21 | -------------------------------------------------------------------------------- /tests/Basic/StaticCtorDtor.spr: -------------------------------------------------------------------------------- 1 | //!! -t "SparrowImplicitLib.spr" -fno-main 2 | 3 | datatype MyType 4 | x: Int 5 | 6 | fun ctor(this: !MyType) 7 | write('c'); write('t'); write('o'); write('r'); write('('); writeLn(')') 8 | fun ctor(this: !MyType, i: Int) 9 | x = i 10 | write('c'); write('t'); write('o'); write('r'); write('('); write(i); writeLn(')') 11 | fun ctor(this, other: !MyType) 12 | x = other.x 13 | write('c'); write('t'); write('o'); write('r'); write('('); write('C'); write(' '); write(x); writeLn(')') 14 | 15 | fun dtor(this: MyType) 16 | write('d'); write('t'); write('o'); write('r'); write('-'); writeLn(x) 17 | 18 | fun ctor() 19 | write('c'); write('t'); write('o'); write('r'); write('-'); writeLn(1) 20 | 21 | fun dtor 22 | write('d'); write('t'); write('o'); write('r'); write('-'); writeLn(1) 23 | 24 | /*fun ctor(i: Int) 25 | write('c'); write('t'); write('o'); write('r'); write('-'); writeLn(2); 26 | */ 27 | 28 | fun ctor() 29 | write('c'); write('t'); write('o'); write('r'); write('-'); writeLn(3) 30 | 31 | fun dtor 32 | write('d'); write('t'); write('o'); write('r'); write('-'); writeLn(2) 33 | 34 | [native("test")] fun test(n: Int) 35 | write('o'); writeLn('k') 36 | 37 | /*<<>>*/ -------------------------------------------------------------------------------- /tests/Basic/Stmt.spr: -------------------------------------------------------------------------------- 1 | //!! -t "SparrowImplicitLib.spr" -fno-main 2 | 3 | fun factorial(n: Int): Int 4 | if n == 0 5 | return 1 6 | else 7 | return n * factorial(n-1) 8 | 9 | fun writeIf { writeLn("IF"); } 10 | fun writeIfErr { writeLn("IF-bad"); } 11 | fun writeMarker { writeLn("---"); } 12 | 13 | fun pre_--(n: !Int): Int { n=n-1; return n; } 14 | 15 | [native("test")] 16 | fun test(n: Int) 17 | factorial(5) writeLnInt 18 | writeMarker 19 | 20 | // If 21 | if true 22 | writeIf // writes 23 | if true ; writeIf // writes 24 | if true ;;; writeIf // writes 25 | if true 26 | if true 27 | if false 28 | writeIfErr 29 | if false ; writeIfErr 30 | if false { writeIfErr } 31 | writeMarker 32 | 33 | // while 34 | n = 5 35 | while --n > 0 // only 4 iterations 36 | "." write 37 | "" writeLn 38 | n = 5 39 | while n > 0 ; n=n-1 40 | "." write 41 | "" writeLn 42 | n = 5 43 | while n > 0 ; n=n-1 ; "." write 44 | "" writeLn 45 | n = 5 46 | while --n > 0 ;{} "." write 47 | "" writeLn 48 | n = 5 49 | while --n > 0 { "." write } 50 | "" writeLn 51 | n = 5 52 | while --n > 0 ; {break;} 53 | "." write 54 | "" writeLn 55 | 56 | /*<<>>*/ 70 | -------------------------------------------------------------------------------- /tests/Basic/String.spr: -------------------------------------------------------------------------------- 1 | //!! -t "SparrowImplicitLib.spr" -fno-main 2 | 3 | fun assert(b: Bool) 4 | if ( !b ) 5 | write('F'); write('A'); write('I'); writeLn('L'); 6 | ; 7 | 8 | fun fassert(b: Bool) 9 | if ( ! !b ) 10 | write('F'); write('A'); write('I'); writeLn('L'); 11 | ; 12 | 13 | [native("test")] fun test(n: Int) 14 | "mumu" 15 | writeLn("Hello, world!") 16 | write("Hello,"); writeLn(" world!") 17 | 18 | let s: StringRef = "abracadabra" 19 | writeLn(s) 20 | write(s.getChar(0)) 21 | write(s.getChar(1)) 22 | write(s.getChar(2)) 23 | write(s.getChar(3)) 24 | write(s.getChar(4)) 25 | write(s.getChar(5)) 26 | write(s.getChar(6)) 27 | write(s.getChar(7)) 28 | write(s.getChar(8)) 29 | write(s.getChar(9)) 30 | writeLn(s.getChar(10)) 31 | 32 | writeLn("---") 33 | 34 | writeLn("Hello," + " world!") 35 | 36 | /*<<>>*/ -------------------------------------------------------------------------------- /tests/Basic/TypeVar.spr: -------------------------------------------------------------------------------- 1 | //!! -t "SparrowImplicitLib.spr" -fno-main 2 | 3 | [ct] let t: Type = Int 4 | [ct] let u: Type 5 | 6 | let x: t = 3 7 | //let y: u = 3; 8 | 9 | [native("test")] fun test(n: Int) 10 | writeLn(x); 11 | 12 | /*<<>>*/ -------------------------------------------------------------------------------- /tests/Basic/ValueToRef.spr: -------------------------------------------------------------------------------- 1 | //!! -t "SparrowImplicitLib.spr" -fno-main 2 | 3 | datatype MyVal 4 | x: Int; 5 | 6 | fun ctor(this: !MyVal, xx: Int) { x = xx; } 7 | 8 | fun value(this: MyVal): Int 9 | return x 10 | 11 | fun print(this: MyVal) 12 | writeLn(x); 13 | 14 | fun increment(this: !MyVal): MyVal 15 | x += 1 16 | return this 17 | 18 | fun next(this: MyVal): MyVal 19 | return MyVal(x+1); 20 | 21 | fun getValue(x: Int): MyVal 22 | return MyVal(x); 23 | 24 | [native("test")] fun test(n: Int) 25 | var v: MyVal 26 | v.print() 27 | writeLn(v.value()) 28 | v.increment().print() 29 | v.print() 30 | v.next() 31 | v.print() 32 | v.next().print() 33 | v.print() 34 | 35 | writeLn("---") 36 | 37 | getValue(100).print() 38 | getValue(110).increment().print() 39 | getValue(120).next().print() 40 | 41 | writeLn("---") 42 | 43 | write("abc".getChar(0)) 44 | write("abc".getChar(1)) 45 | write("abc".getChar(2)) 46 | writeLn("abc".size()) 47 | 48 | /*<<>>*/ -------------------------------------------------------------------------------- /tests/Basic/datatype/storage.spr: -------------------------------------------------------------------------------- 1 | //!! -t "../SparrowImplicitLib.spr" -fno-main 2 | 3 | // Test purpose: datatypes have run-time storage; we can assign and read values from them 4 | 5 | datatype MyType 6 | x: Int 7 | y: Int 8 | 9 | datatype MyType2 10 | x: MyType 11 | y: Float 12 | 13 | var i: Int 14 | var a: MyType 15 | var b: MyType2 16 | 17 | [native("test")] fun test(n: Int) 18 | i = 1 19 | a.x = 10 20 | a.y = 11 21 | b.x.x = 20 22 | b.x.y = 21 23 | 24 | writeLnInt(i) 25 | writeLnInt(a.x) 26 | writeLnInt(a.y) 27 | writeLnInt(b.x.x) 28 | writeLnInt(b.x.y) 29 | 30 | /*<<>>*/ -------------------------------------------------------------------------------- /tests/Basic/exp/dotOper.spr: -------------------------------------------------------------------------------- 1 | //!! -t "../SparrowImplicitLib.spr" -fno-main 2 | 3 | // Test purpose: Check dot operator functionality 4 | 5 | package A 6 | [initCtor] 7 | datatype Ptr(type: Type) 8 | using ValueType = type 9 | 10 | _ptr: @ValueType 11 | 12 | [protected] 13 | fun get(this: Ptr) = _ptr 14 | fun .(this: Ptr) = _ptr 15 | 16 | [initCtor] 17 | datatype MyObj 18 | x: Int 19 | fun print(this: !MyObj) 20 | write("MyObj.print: ") 21 | writeLn(x) 22 | fun print(this: !MyObj, x: Int) 23 | write("MyObj.print: ") 24 | writeLn(x) 25 | 26 | [native("test")] 27 | fun test(n: Int) 28 | var o: MyObj = 0 29 | var p: A.Ptr(MyObj) = o mutToPtr 30 | p.x = 10 31 | p print 32 | p.print 33 | p.x = 20 34 | p print 35 | 36 | p.get().x = 30 37 | p.get().print 38 | p.get print 39 | 40 | /*<<>>*/ 47 | -------------------------------------------------------------------------------- /tests/Basic/fun/callOperator.spr: -------------------------------------------------------------------------------- 1 | //!! -t "../SparrowImplicitLib.spr" -fno-main 2 | 3 | datatype MyType = Int 4 | 5 | fun ()(this: MyType) 6 | writeLn(this.data) 7 | 8 | fun ()(this: MyType, offset: Int) 9 | writeLn(this.data + offset) 10 | 11 | [native("test")] fun test(n: Int) 12 | let obj: MyType = 5 13 | obj() 14 | obj(10) 15 | 16 | /*<<>>*/ -------------------------------------------------------------------------------- /tests/Basic/fun/funExp.spr: -------------------------------------------------------------------------------- 1 | //!! -t "../SparrowImplicitLib.spr" -fno-main 2 | 3 | fun myadd(x,y: Int) = x+y 4 | fun next(x: AnyType) = x+1 5 | 6 | fun one: Int { return 1; } 7 | fun two: Int { return 2; } 8 | fun three = 3 9 | 10 | fun sum(x,y: AnyType) = x+y if typeOf(x) == typeOf(y) 11 | 12 | fun nextAsFloat(x: AnyType): Float = Float(x)+1.0 13 | 14 | datatype Test1 15 | aa: Int 16 | bb: Int 17 | 18 | fun ctor(this: !Test1, a,b: Int) { aa = a; bb = b; } 19 | fun ctor(this, other: !Test1) { aa = other.aa; bb = other.bb; } 20 | 21 | fun a(this: Test1) = this.aa 22 | fun b(this: Test1) = this.bb 23 | 24 | [native("test")] fun test(n: Int) 25 | writeLn(myadd(1,2)) 26 | writeLn(next(5)) 27 | writeLn(one()) 28 | writeLn(two()) 29 | writeLn(three()) 30 | writeLn(sum(5, 6)) 31 | writeLn(sum(3.14, 3.14)) 32 | writeLn(nextAsFloat(3.14)) 33 | writeLn("---") 34 | 35 | let t = Test1(3,5) 36 | writeLn(t.a()) 37 | writeLn(t.b()) 38 | 39 | /*<<>>*/ -------------------------------------------------------------------------------- /tests/Basic/fun/overloadCat.spr: -------------------------------------------------------------------------------- 1 | //!! -t "../SparrowImplicitLib.spr" -fno-main 2 | 3 | fun f1(x: Int const) { writeLn('f1(Int const)'); } 4 | fun f1(x: Int mut) { writeLn('f1(Int mut)'); } 5 | fun f1(x: Int tmp) { writeLn('f1(Int tmp)'); } 6 | 7 | datatype MyData = Int 8 | 9 | fun method(this: MyData) { writeLn('method(const)'); } 10 | fun method(this: !MyData) { writeLn('method(mut)'); } 11 | fun method(this: MyData tmp) { writeLn('method(tmp)'); } 12 | 13 | 14 | [native("test")] fun test(n: Int) 15 | let a: Int const 16 | let b: Int mut 17 | let c: Int tmp 18 | 19 | f1(a) 20 | f1(b) 21 | f1(c) 22 | 23 | writeLn('---') 24 | 25 | let o1: MyData 26 | let o2: !MyData 27 | let o3: MyData tmp 28 | 29 | o1 method 30 | o2 method 31 | o3 method 32 | 33 | /*<<>>*/ -------------------------------------------------------------------------------- /tests/Basic/vars/typeCatFieldsErr.spr: -------------------------------------------------------------------------------- 1 | //!! -t "../SparrowImplicitLib.spr" -fno-main -dump-assembly 2 | 3 | datatype MyObj 4 | x: Int 5 | 6 | fun assign(dest: !Int, src: Int) 7 | dest = src 8 | 9 | fun access 10 | let a: MyObj 11 | let b: !MyObj 12 | let c: MyObj tmp 13 | 14 | writeLn(a.x) 15 | writeLn(b.x) 16 | writeLn(c.x) 17 | 18 | assign(a.x, 3) // ERROR 19 | assign(b.x, 5) 20 | assign(c.x, 7) 21 | 22 | [native("test")] 23 | fun test(n: Int) 24 | access 25 | -------------------------------------------------------------------------------- /tests/Basic2/ConceptOfGeneric.spr: -------------------------------------------------------------------------------- 1 | //!! 2 | 3 | import std.ranges, std.tuple 4 | 5 | datatype FibRange(valType: Type) 6 | using RetType = valType 7 | 8 | _lastTwo: valType*valType = 1 ~ 1 9 | 10 | fun isEmpty(this: FibRange) = false 11 | fun front(this: FibRange) = _lastTwo.v2 12 | fun popFront(this: !FibRange) 13 | _lastTwo = _lastTwo.v2 ~ (_lastTwo.v1 + _lastTwo.v2) 14 | 15 | fun sprMain 16 | for n = take(FibRange(Int)(), 10) 17 | cout << ' ' << n 18 | cout << endl 19 | //isEmpty(3.14) 20 | 21 | /*<<>>*/ 24 | -------------------------------------------------------------------------------- /tests/Basic2/ConceptSpecialization.spr: -------------------------------------------------------------------------------- 1 | //!! 2 | 3 | import std.ranges 4 | 5 | fun getRangeSize(range: RandomAccessRange): Int 6 | cout << "RandomAccessRange fun selected" << endl 7 | return range.size() 8 | 9 | fun getRangeSize(range: Range): Int 10 | cout << "Range fun selected" << endl 11 | var n: Int = 0 12 | while !range.isEmpty(); range.popFront() 13 | ++n 14 | return n 15 | 16 | fun getRangeSize2(range: RandomAccessRange): Int 17 | cout << "RandomAccessRange fun selected" << endl 18 | return range.size() 19 | 20 | fun getRangeSize2(range: Range): Int 21 | cout << "Range fun selected" << endl 22 | var n: Int = 0 23 | while !range.isEmpty(); range.popFront() 24 | ++n 25 | return n 26 | 27 | fun sprMain 28 | cout << getRangeSize(1 ... 10) << endl 29 | cout << getRangeSize2(1 ... 10) << endl 30 | 31 | /*<<>>*/ -------------------------------------------------------------------------------- /tests/Basic2/CtFor.spr: -------------------------------------------------------------------------------- 1 | //!! 2 | 3 | import std.ranges 4 | import std.vector 5 | 6 | [ct] 7 | [initCtor] 8 | datatype MyRange 9 | using RetType = Int 10 | _min, _max: Int 11 | 12 | fun front(this: MyRange) = _min 13 | fun popFront(this: !MyRange) { _min += 1; } 14 | fun isEmpty(this: MyRange) = _min > _max 15 | 16 | fun test1() 17 | [ct] for i = MyRange(0, 4) 18 | cout << ctEval(i) << endl; 19 | ; 20 | 21 | [ct] fun fact(n: Int): Int 22 | if ( n < 2 ) 23 | return 1; 24 | else 25 | return n*fact(n-1); 26 | 27 | fun test2() 28 | [ct] for i = 0..5 29 | cout << ctEval(fact(i)) << endl; 30 | ; 31 | 32 | [ct] fun createVector(min, max: Int): Vector(Int) 33 | let v = Vector(Int)(min..max) 34 | return v 35 | 36 | fun test3() 37 | [ct] let v = createVector(10, 15) 38 | 39 | [ct] for el = v.all() 40 | cout << ctEval(el) << endl; 41 | ; 42 | 43 | fun sprMain 44 | let x = 10 45 | let y = 2 46 | [ct] let yy = 2 47 | 48 | test1() 49 | cout << "---" << endl 50 | test2() 51 | cout << "---" << endl 52 | test3() 53 | 54 | /*<<>>*/ 73 | -------------------------------------------------------------------------------- /tests/Basic2/CtRtCalls.spr: -------------------------------------------------------------------------------- 1 | //!! 2 | 3 | [rt] fun mallocRt() 4 | var pi: @Int = malloc(sizeOf(Int)).asRefOf(Int) 5 | pi = 10 6 | cout << pi << endl 7 | free(UntypedPtr(pi)) 8 | 9 | [ct] fun mallocCt() 10 | var pi: @Int = malloc(sizeOf(Int)).asRefOf(Int) 11 | pi = 11 12 | cout << pi << endl 13 | free(UntypedPtr(pi)) 14 | 15 | fun mallocRtCt() 16 | var pi: @Int = malloc(sizeOf(Int)).asRefOf(Int) 17 | pi = 12 18 | cout << pi << endl 19 | free(UntypedPtr(pi)) 20 | 21 | fun rtCaller() 22 | mallocRtCt(); 23 | 24 | [ct] fun ctCaller() 25 | mallocRtCt(); 26 | 27 | fun test1() 28 | mallocRt() 29 | mallocCt() // Displays 11 at compile-time 30 | 31 | fun test2() 32 | // Call the same rtct function from two different contexts: one at rt, one at ct 33 | rtCaller() 34 | ctCaller() // Display 12 at compile-time 35 | 36 | fun sprMain 37 | let x = 10 38 | let y = 2 39 | [ct] let yy = 2 40 | 41 | test1() 42 | cout << "---" << endl 43 | test2() 44 | 45 | /*<<>>*/ 50 | -------------------------------------------------------------------------------- /tests/Basic2/CtRtParam.spr: -------------------------------------------------------------------------------- 1 | //!! 2 | 3 | import std.ranges 4 | 5 | fun doCompute(x: Int, y: Int ct): Int 6 | cout << "doCompute, ct" << endl 7 | return x * y 8 | 9 | fun doCompute(x: Int, y: Int rt): Int 10 | cout << "doCompute, rt" << endl 11 | return x * y 12 | 13 | fun apply(f: AnyType, n: Int ct) 14 | [ct] if ( n != 0 ) 15 | f() 16 | apply(f, n-1) 17 | else 18 | cout << " @ct" << endl; 19 | 20 | fun apply(f: AnyType, n: Int rt) 21 | for i = 0..n 22 | f(); 23 | cout << " @rt" << endl 24 | 25 | fun sprMain 26 | let x = 10 27 | let y = 2 28 | [ct] let yy = 2 29 | 30 | cout << doCompute(x, y) << endl 31 | cout << doCompute(x, yy) << endl 32 | 33 | cout << "---" << endl 34 | 35 | let n = 5 36 | apply((fun {cout << 'x';}), 5) 37 | apply((fun {cout << 'x';}), n) 38 | 39 | /*<<>>*/ 48 | -------------------------------------------------------------------------------- /tests/Basic2/CtWhile.spr: -------------------------------------------------------------------------------- 1 | //!! 2 | 3 | import std.ranges 4 | import std.vector 5 | 6 | fun test1() 7 | [ct] var i=0 8 | [ct] while i<5; i++ 9 | cout << ctEval(i) << endl; 10 | ; 11 | 12 | [ct] fun fact(n: Int): Int 13 | if ( n < 2 ) 14 | return 1; 15 | else 16 | return n*fact(n-1); 17 | 18 | fun test2() 19 | [ct] var i=0 20 | [ct] while i<5; i++ 21 | cout << ctEval(fact(i)) << endl; 22 | ; 23 | 24 | [ct] fun createVector(min, max: Int): Vector(Int) 25 | let v = Vector(Int)(min..max) 26 | return v 27 | 28 | fun test3() 29 | [ct] let v = createVector(10, 15) 30 | 31 | [ct] var i=0 32 | [ct] while i>>*/ 66 | -------------------------------------------------------------------------------- /tests/Basic2/For.spr: -------------------------------------------------------------------------------- 1 | //!! 2 | 3 | import std.ranges 4 | 5 | fun sprMain 6 | let r = 0..10 7 | for val = r 8 | cout << ' ' << val; 9 | cout << endl 10 | for val = r 11 | cout << ' ' << val; 12 | cout << endl 13 | for val = r 14 | cout << ' ' << val; 15 | cout << endl 16 | 17 | let r2 = 125..130 18 | for val = r2 19 | cout << ' ' << val; 20 | cout << endl 21 | for val: Int = r2 22 | cout << ' ' << val; 23 | cout << endl 24 | for val: Int8 = r2 25 | cout << ' ' << Int(val); 26 | cout << endl 27 | 28 | /*<<>>*/ -------------------------------------------------------------------------------- /tests/Basic2/GenericFunRef.spr: -------------------------------------------------------------------------------- 1 | //!! 2 | 3 | import std.ranges 4 | 5 | fun <<(os: !OutStream, r: Range): typeOf(os) if typeOf(r) != StringRef 6 | var first = true 7 | cout << "(" 8 | for x = r 9 | if ( !first ) 10 | cout << ", "; 11 | first = false 12 | cout << x 13 | cout << ")" 14 | return os 15 | 16 | fun sprMain 17 | let r1 = (1...5) map (fun n = repeat(n*n, n)) 18 | let r2 = r1 map \rangeSize 19 | 20 | cout << r1 << endl 21 | cout << r2 << endl 22 | 23 | /*<<>>*/ 27 | -------------------------------------------------------------------------------- /tests/Basic2/GenericPackage.spr: -------------------------------------------------------------------------------- 1 | //!! 2 | 3 | import std.ranges 4 | 5 | datatype TypePrint(t: Type) 6 | using T = t 7 | 8 | fun ctor(this: !TypePrint) 9 | cout << 'TypePrint.ctor ' << TypeOp.description(T) << endl 10 | 11 | package GenPackage(t: Type) 12 | using MyType = t rt 13 | 14 | // Causes a global print for all the instantiations 15 | let printer: TypePrint(t) 16 | 17 | fun getType: StringRef = TypeOp.description(MyType) 18 | 19 | fun printLine 20 | cout << '---\n' 21 | 22 | fun sprMain 23 | // Instantiate two packages by calling functions from there 24 | GenPackage(Int).printLine 25 | GenPackage(Float).printLine 26 | 27 | // Instantiate another one with an using 28 | using MyCharPackage = GenPackage(Char) 29 | 30 | // Get function pointers from a function in the generic package 31 | var f: FunctionPtr(StringRef rt) 32 | f = \(GenPackage(Int).getType) 33 | cout << f() << endl 34 | f = \(GenPackage(Float).getType) 35 | cout << f() << endl 36 | f = \(MyCharPackage.getType) 37 | cout << f() << endl 38 | 39 | /*<<>>*/ 49 | -------------------------------------------------------------------------------- /tests/Basic2/Precedence.spr: -------------------------------------------------------------------------------- 1 | //!! 2 | 3 | fun writeLnBool(b: Bool) 4 | cout << ife(b, "true", "false") << endl 5 | 6 | fun sprMain 7 | cout << (1 + 2 * 3) << endl 8 | writeLnBool(true || true && false) 9 | writeLnBool(1==1 || 2==2 && 1==2) 10 | writeLnBool(1<=1 || 2>=2 && 1>=2) 11 | 12 | /*<<>>*/ -------------------------------------------------------------------------------- /tests/Basic2/Regular.spr: -------------------------------------------------------------------------------- 1 | //!! 2 | 3 | concept Regular(x) if ( 4 | isValid(TypeOp.copyVal(x).ctor()) // Default construction 5 | && isValid(TypeOp.copyVal(x).ctor(x)) // Copy construction 6 | && isValid(TypeOp.copyVal(x).dtor()) // Destruction 7 | && typeOf(x == x) == Bool // Equality is defined 8 | ) 9 | 10 | [noDefault, convert] 11 | datatype NullType 12 | ; 13 | 14 | fun ctor(this: !NullType) {} 15 | [convert] fun ctor(this: !NullType, other: AnyType) {} 16 | fun dtor(this: NullType) {} 17 | 18 | fun ==(this, other: NullType) = true 19 | fun ==(this, other: AnyType) = false 20 | 21 | fun testRegular(x: Regular) 22 | cout << TypeOp.description(typeOf(x)) << " is Regular\n"; 23 | 24 | fun testRegular(x: AnyType) if !Regular(x) 25 | cout << TypeOp.description(typeOf(x)) << " is not Regular\n"; 26 | 27 | datatype MyType 28 | ; 29 | // Operators are implicitly defined 30 | 31 | package Isolated 32 | [noDefault] 33 | datatype EmptyType 34 | ; 35 | 36 | fun sprMain 37 | testRegular(1) 38 | testRegular(1.0) 39 | let o: NullType 40 | let o1: MyType 41 | let o2: Isolated.EmptyType 42 | testRegular(o) 43 | testRegular(o1) 44 | testRegular(o2) 45 | /*<<>>*/ 52 | 53 | -------------------------------------------------------------------------------- /tests/Bugs/CastOnAssignment.spr: -------------------------------------------------------------------------------- 1 | //!! 2 | 3 | fun sprMain 4 | var dest: Int = 10 5 | let otherVal: Int64 = 13 6 | dest = otherVal // ERROR 7 | cout << dest << endl 8 | -------------------------------------------------------------------------------- /tests/Bugs/GenericWithCtConcept.spr: -------------------------------------------------------------------------------- 1 | //!! 2 | 3 | datatype TestData = Int 4 | 5 | concept MyConcept(x) 6 | 7 | [ct] 8 | fun getCtData(val: Int): TestData 9 | return TestData(val) 10 | 11 | fun testConcept(x: MyConcept) 12 | ; 13 | 14 | fun copyFromtCt(dest: !MyConcept, src: MyConcept ct) 15 | dest.data = src.data 16 | 17 | fun sprMain 18 | var x: TestData 19 | 20 | testConcept(x) 21 | testConcept(getCtData(3)) 22 | 23 | copyFromtCt(x, getCtData(3)) 24 | 25 | cout << "OK\n" 26 | 27 | /*<<>>*/ -------------------------------------------------------------------------------- /tests/Bugs/NullConstant.spr: -------------------------------------------------------------------------------- 1 | 2 | fun sprMain 3 | let p: @Int = null 4 | 5 | cout << (p === null) << endl 6 | cout << (p !== null) << endl 7 | /*<<>>*/ 11 | -------------------------------------------------------------------------------- /tests/Bugs/Overload.spr: -------------------------------------------------------------------------------- 1 | 2 | import std.algorithms 3 | 4 | fun f(a: Int, b: Int) 5 | cout << "f a b " << a << " " << b << endl 6 | 7 | fun f(x: Float) 8 | cout << "f x " << x << endl 9 | 10 | fun f(p: Int*Int) 11 | cout << "f p " << p._1 << " " << p._2 << endl 12 | 13 | fun sprMain 14 | f(2, 3) 15 | f(2.0) 16 | f(3 ~ 4) 17 | /*<<>>*/ 22 | -------------------------------------------------------------------------------- /tests/Bugs/ParenInGeneric.spr: -------------------------------------------------------------------------------- 1 | //!! -t ../Basic/SparrowImplicitLib.spr -fno-main 2 | 3 | datatype MyVector(t: Type) 4 | start, end: t 5 | 6 | fun ==(this, other: MyVector): Bool = start == other.start && end == other.end 7 | fun !=(this, other: MyVector): Bool = !(this == other) 8 | 9 | fun assert(b: Bool) 10 | if ( !b ) 11 | writeLn("Failure") 12 | 13 | fun assertF(b: Bool) 14 | if ( b ) 15 | writeLn("Failure") 16 | 17 | [native("test")] 18 | fun test(n: Int) 19 | var v11: MyVector(Int) 20 | v11.start = 4 21 | v11.end = 5 22 | var v12: MyVector(Int) 23 | v12.start = 4 24 | v12.end = 4 25 | 26 | var v21: MyVector(Float) 27 | v21.start = 10.0 28 | v21.end = 15.2 29 | var v22: MyVector(Float) 30 | v22.start = 10.0 31 | v22.end = 11.2 32 | 33 | assert(v11 != v12) 34 | assertF(v11 == v12) 35 | assert(v21 != v22) 36 | assertF(v21 == v22) 37 | writeLn("OK") 38 | 39 | /*<<>>*/ -------------------------------------------------------------------------------- /tests/Bugs/SpecializationOnCt.spr: -------------------------------------------------------------------------------- 1 | 2 | fun f(x: Int) 3 | cout << "RT: f(" << x << ")\n"; 4 | 5 | fun f(x: Int ct) 6 | cout << "CT: f(" << x << ")\n"; 7 | 8 | fun g(x: Int, y: Int) 9 | cout << "RT: g(" << x << ", " << y << ")\n"; 10 | 11 | fun g(x: Int ct, y: Int) 12 | cout << "CT: g(" << x << ", " << y << ")\n"; 13 | 14 | fun regexMatch(re, str: StringRef): Bool 15 | cout << "RT: regexMatch(" << re << ", " << str << ")\n" 16 | return false 17 | 18 | fun regexMatch(re: StringRef ct, str: StringRef): Bool 19 | cout << "CT: regexMatch(" << re << ", " << str << ")\n" 20 | return false 21 | 22 | fun sprMain 23 | let n = 5 24 | 25 | f(n) 26 | f(6) 27 | 28 | g(n, n) 29 | g(6, n) 30 | 31 | let str = "mumu" 32 | [ct] let strCt = "bubu" 33 | regexMatch(str, "testStr") 34 | regexMatch(strCt, "testStr") 35 | /*<<>>*/ 43 | -------------------------------------------------------------------------------- /tests/Bugs/StaticGlobal.spr: -------------------------------------------------------------------------------- 1 | //!! 2 | 3 | let a = 2048 4 | 5 | fun ctor 6 | cout << 42 << endl; 7 | 8 | datatype MyObj(n: Int ct) 9 | using b = 1024 10 | using c = n 11 | 12 | fun sprMain 13 | cout << MyObj(0).b << endl 14 | cout << a << endl 15 | cout << MyObj(4096).c << endl 16 | /*<<>>*/ 22 | -------------------------------------------------------------------------------- /tests/Bugs/TwiceFor.spr: -------------------------------------------------------------------------------- 1 | //!! 2 | 3 | import std.ranges 4 | 5 | fun sprMain 6 | let r = 0 .. 10 7 | for val = r 8 | cout << ' ' << val 9 | cout << endl 10 | for val = r 11 | cout << ' ' << val 12 | cout << endl 13 | 14 | /*<<>>*/ -------------------------------------------------------------------------------- /tests/Bugs/VectorOfCtClass.spr: -------------------------------------------------------------------------------- 1 | //!! 2 | 3 | import std.vector 4 | 5 | [ct] datatype TestCt 6 | { 7 | } 8 | 9 | fun test(x: !Vector(TestCt)) 10 | 11 | fun sprMain 12 | { 13 | } 14 | -------------------------------------------------------------------------------- /tests/Bugs/WhileVarCond.spr: -------------------------------------------------------------------------------- 1 | fun sprMain 2 | var a: Bool 3 | a = true 4 | let ra: @Bool = a mutToPtr 5 | while a 6 | break 7 | while ra 8 | break -------------------------------------------------------------------------------- /tests/Bugs/test.spr: -------------------------------------------------------------------------------- 1 | //!! 2 | 3 | // Test purpose: make sure we are not using files from std lib 4 | 5 | import std.ranges 6 | 7 | fun sprMain 8 | cout << 'OK\n' 9 | 10 | /*<<>>*/ -------------------------------------------------------------------------------- /tests/CompilerApi/ApiSmokeTest.spr: -------------------------------------------------------------------------------- 1 | //!! 2 | 3 | import meta.sparrowNodes, meta.featherNodes 4 | 5 | fun sprMain 6 | { 7 | } 8 | -------------------------------------------------------------------------------- /tests/CompilerApi/Diagnostic.spr: -------------------------------------------------------------------------------- 1 | //!! 2 | 3 | import meta.compilerCore 4 | 5 | fun sprMain // ERROR - introduced by the last meta.report 6 | [ct] let loc = mkLocation(currentSourceCode, mkLineCol(5, 5), mkLineCol(5, 12)) 7 | 8 | [ct] let diag1 = mkDiagnostic(diagInfo, loc, "Some information") 9 | report(diag1) 10 | 11 | [ct] let diag2 = mkDiagnostic(diagWarning, loc, "Some warning") 12 | report(diag2) 13 | 14 | report(diagError, loc, "Error at the beginning of the function") 15 | 16 | [ct] let sc = currentSourceCode 17 | [ct] let sc2 = sourceCodeFromFilename("/Users/lucteo/work/sparrow/dev/tests/CompilerApi/Diagnostic.spr") 18 | 19 | cout << (sc filename) << endl 20 | // cout << (sc2 filename) << endl; 21 | 22 | if ( sc == sc2 ) 23 | cout << "equal\n"; 24 | else 25 | cout << "not equal\n"; 26 | /*--<<>>*/ 31 | -------------------------------------------------------------------------------- /tests/Examples/Power.spr: -------------------------------------------------------------------------------- 1 | //!! 2 | 3 | import math = math 4 | 5 | fun pow(x: Float, n: Int ct): Float 6 | if ( n == 0 ) 7 | return 1.0; 8 | else if ( n == 1 ) 9 | return x; 10 | else 11 | return pow(x*x, n/2) * pow(x, n%2); 12 | 13 | fun pow(x: Float, n: Int): Float 14 | if ( n == 0 ) 15 | return 1.0; 16 | else if ( n == 1 ) 17 | return x; 18 | else 19 | return pow(x*x, n/2) * pow(x, n%2); 20 | 21 | fun pow(x: Float, n: Float): Float 22 | return math.pow(x, n); 23 | 24 | fun sprMain 25 | let x = 10.0 26 | let yd = 2.0 27 | let yn = 2 28 | let r1 = pow(x, yd) 29 | let r2 = pow(x, yn) 30 | let r3 = pow(x, 2) 31 | 32 | cout << r1 << endl 33 | cout << r2 << endl 34 | cout << r3 << endl 35 | 36 | /*<<>>*/ -------------------------------------------------------------------------------- /tests/Examples/Speak.spr: -------------------------------------------------------------------------------- 1 | import os = os 2 | 3 | [ct] let hello = "Hello, world!" 4 | [ct] let name = "I am the Sparrow compiler!" 5 | [ct] let smart = "Unlike other compilers, I am smart." 6 | [ct] let canDo = "I can run any kind of algorithm and I can execute any kind of program during compilation." 7 | [ct] let exampl = "For example, in this program I composed a text at compile time and called an external program to synthesize it." 8 | [ct] let more = "As you will shortly see, I can do much more." 9 | [ct] let exit = "Now, I will let my dear friend Lucian to continue the presentation. Thank you, and good bye!" 10 | 11 | [ct] fun getMessage = hello+" "+name+" "+smart+" "+canDo+" "+exampl+" "+more+" "+exit 12 | 13 | [ct] fun say(message: StringRef) 14 | cout << endl << message << endl 15 | os.systemCall("say \"" + message + "\"") 16 | 17 | [ct] fun ctor 18 | say( getMessage() ) 19 | -------------------------------------------------------------------------------- /tests/Examples/llvm-compile: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | echo "Compiling..." 4 | ../../.out/Release/llvm/llvm-as $1 -o $1.bc 5 | ../../.out/Release/llvm/opt $1.bc -o $1.opt.bc -O3 6 | #cp $1.bc $1.opt.bc 7 | ../../.out/Release/llvm/llc $1.opt.bc -filetype=obj 8 | gcc $1.opt.o -o $1.out -lm 9 | rm $1.bc 10 | rm $1.opt.bc 11 | rm $1.opt.o 12 | echo "Done" 13 | -------------------------------------------------------------------------------- /tests/Examples/others/mph/Makefile: -------------------------------------------------------------------------------- 1 | HEADERS = ../src/cmph.h 2 | INCLUDE_DIRS = -I ../src 3 | LIBS = ../src/.libs/libcmph.a 4 | 5 | default: sparrow_cmp_test 6 | 7 | sparrow_cmp_test.o: sparrow_cmp_test.cpp $(HEADERS) 8 | clang++ -O3 -c sparrow_cmp_test.cpp -o sparrow_cmp_test.o $(INCLUDE_DIRS) 9 | 10 | sparrow_cmp_test: sparrow_cmp_test.o 11 | clang++ sparrow_cmp_test.o $(LIBS) -o sparrow_cmp_test -lm -L /usr/lib -L /usr/lib/i386-linux-gnu 12 | 13 | clean: 14 | -rm -f sparrow_cmp_test.o 15 | -rm -f sparrow_cmp_test -------------------------------------------------------------------------------- /tests/Examples/others/regex/Makefile: -------------------------------------------------------------------------------- 1 | all: dfa0 dfa1 nfa 2 | 3 | dfa0: dfa0.o 4 | gcc -Wall -O3 -o dfa0 dfa0.o 5 | 6 | dfa1: dfa1.o 7 | gcc -Wall -O3 -o dfa1 dfa1.o 8 | 9 | nfa: nfa.o 10 | gcc -Wall -O3 -o nfa nfa.o 11 | 12 | dfa0.o: dfa0.c 13 | gcc -Wall -O3 -c dfa0.c 14 | 15 | dfa1.o: dfa1.c 16 | gcc -Wall -O3 -c dfa1.c 17 | 18 | nfa.o: nfa.c 19 | gcc -Wall -O3 -c nfa.c 20 | 21 | clean: 22 | rm -f *~ *.o dfa0 dfa1 nfa 23 | 24 | -------------------------------------------------------------------------------- /tests/Examples/queen-art.txt: -------------------------------------------------------------------------------- 1 | 2 2 |   3 |   4 |   5 |   6 | /\/\/\ 7 | \____/ 8 | /\/\/\ 9 | \____/ 10 | -------------------------------------------------------------------------------- /tests/Frontend/Identifiers.spr: -------------------------------------------------------------------------------- 1 | module Ids 2 | 3 | fun pow(x,y: Int) = 1 4 | fun **(x,y: Int) = 2 5 | fun !@#$%^&*(x,y: Int) = 3 6 | fun <>(x,y: Int) = 4 7 | fun ::(x,y: Int) = 5 8 | fun a_::(x,y: Int) = 6 9 | 10 | fun sprMain 11 | cout << pow(1,2) << endl 12 | cout << Ids.**(1,2) << endl 13 | cout << Ids.!@#$%^&*(1,2) << endl 14 | cout << Ids.<>(1,2) << endl 15 | cout << Ids.::(1,2) << endl 16 | cout << a_::(1,2) << endl 17 | /*<<>>*/ 25 | -------------------------------------------------------------------------------- /tests/Frontend/Numbers.spr: -------------------------------------------------------------------------------- 1 | fun sprMain 2 | cout << 1234 << '\n' 3 | cout << 0xff << '\n' 4 | cout << 0o777 << '\n' 5 | cout << 0b11111111 << '\n' 6 | cout << 3.14 << '\n' 7 | cout << '---\n' 8 | 9 | cout << 1_234 << '\n' 10 | cout << 0xf_f << '\n' 11 | cout << 0o7_7_7 << '\n' 12 | cout << 0b1111_1111 << '\n' 13 | cout << 3.1_4 << '\n' 14 | cout << '---\n' 15 | 16 | cout << 0.314e1 << '\n' 17 | cout << 0.314e+1 << '\n' 18 | cout << 314.e-2 << '\n' 19 | 20 | /*<<>>*/ 37 | -------------------------------------------------------------------------------- /tests/Frontend/Smoke.spr: -------------------------------------------------------------------------------- 1 | import Nothing 2 | 3 | using Nothing.* 4 | 5 | package A 6 | package B 7 | datatype C 8 | a: Int 9 | b: Bool 10 | 11 | fun ctor(this: @C, aa: Int, bb: Bool) { a=aa; b=bb; } 12 | fun f(x: Int): Int 13 | return a 14 | 15 | ( . ) // ERROR 16 | -------------------------------------------------------------------------------- /tests/Frontend/StringAndDsl.spr: -------------------------------------------------------------------------------- 1 | 2 | fun sprMain 3 | cout << "Hello, world!" << endl 4 | cout << <{Hello, world!}> << endl 5 | cout << <{Hello, 6 | 7 | world!}> << endl 8 | cout << <{Hello,{} >"world"!}> << endl 9 | /*<<"world"! 16 | >>>*/ 17 | -------------------------------------------------------------------------------- /tests/Imports/HeaderA.spr: -------------------------------------------------------------------------------- 1 | 2 | let a = Int(1) 3 | -------------------------------------------------------------------------------- /tests/Imports/HeaderB.spr: -------------------------------------------------------------------------------- 1 | 2 | let b = Int(2) 3 | -------------------------------------------------------------------------------- /tests/Imports/HeaderC.spr: -------------------------------------------------------------------------------- 1 | import HeaderA 2 | import HeaderB 3 | 4 | let c = Int(3) 5 | -------------------------------------------------------------------------------- /tests/Imports/HeaderD.spr: -------------------------------------------------------------------------------- 1 | import HeaderA 2 | import HeaderC 3 | 4 | let d = Int(4) 5 | -------------------------------------------------------------------------------- /tests/Imports/ImportComplex.spr: -------------------------------------------------------------------------------- 1 | //!! -t "../Basic/SparrowImplicitLib.spr" -fno-main 2 | import HeaderA 3 | import HeaderB 4 | import HeaderC 5 | import HeaderD 6 | 7 | [native("test")] fun test(n: Int) 8 | writeLn(a) 9 | writeLn(b) 10 | writeLn(c) 11 | writeLn(d) 12 | writeLn("Ok") 13 | 14 | /*<<>>*/ 21 | -------------------------------------------------------------------------------- /tests/Imports/ImportComplex2.spr: -------------------------------------------------------------------------------- 1 | //!! -t "../Basic/SparrowImplicitLib.spr" -fno-main 2 | import HeaderD 3 | import HeaderC 4 | import HeaderB 5 | import HeaderA 6 | 7 | [native("test")] fun test(n: Int) 8 | writeLn("Ok") 9 | 10 | /*<<>>*/ 13 | -------------------------------------------------------------------------------- /tests/Imports/ImportDirect.spr: -------------------------------------------------------------------------------- 1 | //!! -t "../Basic/SparrowImplicitLib.spr" -fno-main 2 | import "HeaderA.spr" 3 | 4 | [native("test")] fun test(n: Int) 5 | a = 100 6 | writeLn("Ok") 7 | 8 | /*<<>>*/ 11 | -------------------------------------------------------------------------------- /tests/Imports/ImportInTheMiddle.spr: -------------------------------------------------------------------------------- 1 | //!! -t "../Basic/SparrowImplicitLib.spr" -fno-main 2 | 3 | package Foo1 4 | fun test1 5 | Foo2.a = 1 6 | Foo2.b = 2 7 | Foo2.c = 3 8 | Foo2.d = 4 9 | 10 | package Foo2 11 | import HeaderD 12 | import HeaderC 13 | import HeaderB 14 | import HeaderA 15 | 16 | [native("test")] fun test(n: Int) 17 | Foo1.test1 18 | writeLn(Foo2.a) 19 | writeLn(Foo2.b) 20 | writeLn(Foo2.c) 21 | writeLn(Foo2.d) 22 | 23 | /*<<>>*/ 29 | -------------------------------------------------------------------------------- /tests/Imports/ImportRelativeFile.spr: -------------------------------------------------------------------------------- 1 | //!! -t "../Basic/SparrowImplicitLib.spr" -fno-main 2 | import "../Imports/HeaderA.spr" 3 | 4 | [native("test")] fun test(n: Int) 5 | a = 100 6 | writeLn("Ok") 7 | 8 | /*<<>>*/ 11 | -------------------------------------------------------------------------------- /tests/Imports/ImportTwice.spr: -------------------------------------------------------------------------------- 1 | //!! -t "../Basic/SparrowImplicitLib.spr" -fno-main 2 | import HeaderA 3 | import HeaderA 4 | 5 | import HeaderA, HeaderB, HeaderA 6 | 7 | [native("test")] fun test(n: Int) 8 | writeLn("Ok") 9 | 10 | /*<<>>*/ 13 | -------------------------------------------------------------------------------- /tests/Imports/SelectiveImport.spr: -------------------------------------------------------------------------------- 1 | import std.ranges(Range, .., map, filter) 2 | 3 | fun sprMain 4 | cout << "Ok" << endl 5 | 6 | /*<<>>*/ 9 | -------------------------------------------------------------------------------- /tests/Logic/Antiquotation.spr: -------------------------------------------------------------------------------- 1 | //!! 2 | import logic = logic.prolog 3 | import std.string 4 | 5 | using sunVar = "sun" 6 | fun getSun: String { cout << ""; return "sun"; } 7 | 8 | logic.compileProlog(" 9 | orbits(mercury, sun). 10 | orbits(venus, sun). 11 | orbits(earth, sun). 12 | orbits(mars, sun). 13 | orbits(moon, earth). 14 | orbits(phobos, mars). 15 | orbits(deimos, mars). 16 | 17 | planet(P) :- orbits(P, sun). 18 | planet2(P) :- orbits(P, $sunVar). 19 | planet3(P) :- orbits(P, ${\"sun\"}). 20 | planet4(P) :- orbits(P, ${getSun()}). 21 | planet5(P) :- orbits(P, ${\"s\"+\"u\"+\"n\"}). 22 | ") 23 | 24 | fun sprMain 25 | cout << "Is Mercury orbiting Sun? " << orbits("mercury", "sun")() << endl 26 | cout << "Is Mercury a planet? " << planet("mercury")() << endl 27 | cout << "Is Mercury a planet (2)? " << planet2("mercury")() << endl 28 | cout << "Is Mercury a planet (3)? " << planet3("mercury")() << endl 29 | cout << "Is Mercury a planet (4)? " << planet4("mercury")() << endl 30 | cout << "Is Mercury a planet (5)? " << planet5("mercury")() << endl 31 | 32 | /*<<true 38 | Is Mercury a planet (5)? true 39 | >>>*/ 40 | -------------------------------------------------------------------------------- /tests/Logic/FibOptTest.spr: -------------------------------------------------------------------------------- 1 | //!! 2 | import logic.prologFrontend 3 | 4 | fun fib_native(p_1: Int, p_2: !Int): Bool 5 | var l2_X2: Int = Uninitialized() 6 | var l2_Y2: Int = Uninitialized() 7 | var l2_X1: Int = Uninitialized() 8 | var l2_Y1: Int = Uninitialized() 9 | return ( p_1 == 0 && p_2 =/ 0 10 | || p_1 == 1 && p_2 =/ 1 11 | || l2_X2 =/ (p_1 - 2) && fib_native(l2_X2, l2_Y2) && l2_X1 =/ (p_1 - 1) && fib_native(l2_X1, l2_Y1) && p_2 =/ (l2_Y1 + l2_Y2) 12 | ) 13 | datatype fib_pred_wrapper 14 | p_1: LInt 15 | p_2: LInt 16 | fun ctor(this: !fib_pred_wrapper, p_1: !LInt, p_2: !LInt) 17 | this.p_1 ctor p_1 18 | this.p_2 ctor p_2 19 | fun ()(this: !fib_pred_wrapper): Bool 20 | if ( p_1.isNull() ) 21 | return false 22 | p_2 = Int() 23 | return fib_native(p_1.get(), p_2.get()) 24 | fun fib(p_1: !LInt, p_2: !LInt): Predicate = fib_pred_wrapper(p_1, p_2) 25 | 26 | fun sprMain 27 | if ( programArgs.size() < 2 ) 28 | return 29 | var n = programArgs(1) asInt 30 | 31 | var res: LInt 32 | cout << fib(n, res)() << endl 33 | cout << "res=" << res.get() << endl 34 | 35 | /*<<>>*/ 39 | 40 | /*<<>>*/ 44 | -------------------------------------------------------------------------------- /tests/Logic/FibProlog.spr: -------------------------------------------------------------------------------- 1 | //!! 2 | import logic.prologFrontend 3 | import "Fibonacci.pl" 4 | 5 | fun sprMain 6 | if ( programArgs.size() < 2 ) 7 | return 8 | var n = programArgs(1) asInt 9 | 10 | var res: LInt 11 | fib(n, res)() 12 | cout << res.get() 13 | 14 | /*<<>>*/ 16 | 17 | /*<<>>*/ 19 | -------------------------------------------------------------------------------- /tests/Logic/FibPrologErr.spr: -------------------------------------------------------------------------------- 1 | //!! 2 | import logic.prologFrontend 3 | //import "FibonacciErr.pl"; 4 | 5 | compileProlog(" 6 | fib(0,0). 7 | fib(1,1). 8 | fib(X,Y) :- 9 | %% pred(X),, 10 | X2 is X-2, fib(X2, Y2), 11 | X1 is X-1, fib(X1, Y1), 12 | Y is Y1 + Y2. 13 | fib(sun, earth). %% ERROR 14 | ") 15 | 16 | fun sprMain 17 | if ( programArgs.size() < 2 ) 18 | return 19 | var n = programArgs(1) asInt 20 | 21 | var res: LInt 22 | cout << fib(n, res)() << endl 23 | cout << "res=" << res.get() << endl 24 | -------------------------------------------------------------------------------- /tests/Logic/FibTest.spr: -------------------------------------------------------------------------------- 1 | //!! 2 | import logic.prologFrontend 3 | 4 | fun fib(p_1: !LInt, p_2: !LInt): Predicate 5 | var l2_X2: LInt 6 | var l2_Y2: LInt 7 | var l2_X1: LInt 8 | var l2_Y1: LInt 9 | return ( p_1 /=/ 0 && p_2 /=/ 0 10 | || p_1 /=/ 1 && p_2 /=/ 1 11 | || l2_X2 /=/ (p_1 /-/ 2) && rec(\fib, l2_X2, l2_Y2) && l2_X1 /=/ (p_1 /-/ 1) && rec(\fib, l2_X1, l2_Y1) && p_2 /=/ (l2_Y1 /+/ l2_Y2) 12 | ) 13 | 14 | fun sprMain 15 | if ( programArgs.size() < 2 ) 16 | return 17 | var n = programArgs(1) asInt 18 | 19 | var res: LInt 20 | cout << fib(n, res)() << endl 21 | cout << "res=" << res.get() << endl 22 | 23 | /*<<>>*/ 27 | 28 | /*<<>>*/ 32 | -------------------------------------------------------------------------------- /tests/Logic/Fibonacci.pl: -------------------------------------------------------------------------------- 1 | %% #!/usr/bin/swipl -q -t main -f 2 | 3 | fib(0,0). 4 | fib(1,1). 5 | fib(X,Y) :- 6 | X2 is X-2, fib(X2, Y2), 7 | X1 is X-1, fib(X1, Y1), 8 | Y is Y1 + Y2. 9 | 10 | %% main :- fib(25, Res), write(Res), nl, halt. -------------------------------------------------------------------------------- /tests/Logic/FibonacciErr.pl: -------------------------------------------------------------------------------- 1 | fib(0,0). 2 | fib(1,1). 3 | fib(X,Y) :- 4 | X2 is X-2, fib(X2, Y2), 5 | X1 is X-1, fib(X1, Y1), 6 | Y is Y1 + Y2. 7 | fib(sun, earth). %% ERROR 8 | -------------------------------------------------------------------------------- /tests/Logic/ImportProlog.spr: -------------------------------------------------------------------------------- 1 | //!! 2 | import logic.prologFrontend 3 | import "Solar.pl" 4 | 5 | fun sprMain 6 | if ( programArgs.size() < 2 ) 7 | return 8 | var n = programArgs(1) asInt 9 | 10 | if n == 1; test1 11 | //else if n == 2; test2 12 | //else if n == 3; test3 13 | //else if n == 4; test4 14 | 15 | fun test1 16 | cout << "Is Mercury orbiting Sun? " << orbits("mercury", "sun")() << endl 17 | cout << "Is Mercury a planet? " << planet("mercury")() << endl 18 | /*<<>>*/ 22 | -------------------------------------------------------------------------------- /tests/Logic/PrologErr1.spr: -------------------------------------------------------------------------------- 1 | //!! 2 | import logic = logic.prolog 3 | 4 | logic.compileProlog(" 5 | orbits(mercury, sun). 6 | orbits(venus, sun). 7 | orbits(earth, sun). 8 | orbits(mars, sun). 9 | orbits(moon, earth). 10 | orbits(phobos, mars). 11 | orbits(deimos, mars). 12 | 13 | planet(P) :- orbits(P, sun).# // ERROR 14 | 15 | satellite(S) :- orbits(S, P), planet(P). 16 | ") 17 | 18 | fun test1 19 | var x: LStr 20 | var pred = satellite(x) 21 | -------------------------------------------------------------------------------- /tests/Logic/PrologErr2.spr: -------------------------------------------------------------------------------- 1 | //!! 2 | import logic = logic.prolog 3 | 4 | logic.compileProlog(" 5 | orbits(mercury, sun). 6 | orbits(venus, sun). 7 | orbits(earth, sun). 8 | orbits(mars, sun). 9 | orbits(moon, earth). 10 | orbits(phobos, mars). 11 | orbits(deimos, mars). 12 | 13 | planet(P) :- orbits(P, sun), bubu ERROR 14 | 15 | satellite(S) :- orbits(S, P), planet(P). 16 | ") 17 | 18 | fun test1 19 | var x: LStr 20 | var pred = satellite(x) 21 | -------------------------------------------------------------------------------- /tests/Logic/PrologErr3.spr: -------------------------------------------------------------------------------- 1 | //!! 2 | import logic = logic.prolog 3 | 4 | logic.compileProlog(" 5 | orbits(mercury, sun). 6 | orbits(venus, sun). 7 | orbits(earth, sun). 8 | orbits(mars, sun). 9 | orbits(moon, earth). 10 | orbits(phobos, mars). 11 | orbits(deimos, mars). 12 | 13 | planet(P) :- orbits(P, sun). 14 | 15 | satellite(S) :- orbits(S, P), planet(P). 16 | ") 17 | 18 | fun test1 19 | var x: logic.LStr 20 | var pred = satellite(x) 21 | var pred = satellite(x,x) // ERROR 22 | -------------------------------------------------------------------------------- /tests/Logic/Solar.pl: -------------------------------------------------------------------------------- 1 | orbits(mercury, sun). 2 | orbits(venus, sun). 3 | orbits(earth, sun). 4 | orbits(mars, sun). 5 | orbits(moon, earth). 6 | orbits(phobos, mars). 7 | orbits(deimos, mars). 8 | 9 | planet(P) :- orbits(P, sun). 10 | 11 | satellite(S) :- orbits(S, P), planet(P). 12 | -------------------------------------------------------------------------------- /tests/Logic/test/cpp/Fib.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | using namespace std; 5 | 6 | int fibonacciRec(int n) 7 | { 8 | if ( n == 0 ) 9 | return 0; 10 | if ( n == 1 ) 11 | return 1; 12 | 13 | return fibonacciRec(n - 1) + fibonacciRec(n - 2); 14 | } 15 | 16 | void fibonacciRec2(int n, int& res) 17 | { 18 | if ( n == 0 ) 19 | res = 0; 20 | else if ( n == 1 ) 21 | res = 1; 22 | else 23 | { 24 | int r1, r2; 25 | fibonacciRec2(n-1, r1); 26 | fibonacciRec2(n-2, r2); 27 | res = r1 + r2; 28 | } 29 | } 30 | 31 | 32 | int main(int argc, const char** argv) 33 | { 34 | if ( argc < 2 ) 35 | return -1; 36 | int n = atoi(argv[1]); 37 | cout << fibonacciRec(n); 38 | // int res; 39 | // fibonacciRec2(n, res); 40 | // cout << res; 41 | return 0; 42 | } -------------------------------------------------------------------------------- /tests/Par/ParForTest.spr: -------------------------------------------------------------------------------- 1 | //! ! -O3 2 | // -g -O1 -dump-assembly 3 | 4 | import std.compilerInfo 5 | 6 | [ct] if platformName == 'Darwin' 7 | import par.tasks 8 | import par.parFor 9 | import par.atomic 10 | import test 11 | 12 | var counter: Int Atomic 13 | var outOfOrderCount: Int Atomic 14 | 15 | fun foo(x: Int) 16 | let curIdx = counter++ 17 | if ( curIdx != x ) 18 | outOfOrderCount++ 19 | sleepMs(0) 20 | 21 | fun sprMain 22 | if ( programArgs.size() < 2 ) 23 | return 24 | let n = programArgs(1) asInt 25 | 26 | 0..n parFor \foo 27 | 28 | //cout << "Num out of order: " << (outOfOrderCount load) << endl 29 | assertGt(outOfOrderCount load, 0) 30 | assertLe(outOfOrderCount load, n) 31 | else 32 | fun sprMain 33 | ; 34 | 35 | /*<<>>*/ 37 | 38 | /*<<>>*/ 40 | 41 | -------------------------------------------------------------------------------- /tests/PerfTests/FibRanges/Makefile: -------------------------------------------------------------------------------- 1 | 2 | GCC=clang 3 | OPT_LEVEL=-O2 4 | C_FLAGS= 5 | C_LIBS=-lc 6 | CPP_FLAGS=-std=c++11 7 | CPP_LIBS=-lc -lstdc++ 8 | 9 | SPARROWC=~/work/sparrow/dev/.out/Release/SparrowCompiler 10 | 11 | all: fib_op.cpp.out fib_op.c.out fib_op.spr.out fib_op_base.spr.out 12 | 13 | %.spr.out: %.spr 14 | $(SPARROWC) -o $@ $< $(OPT_LEVEL) $(DEBUG_FLAGS) 15 | 16 | %.c.out: %.c 17 | $(GCC) -o $<.o $< -c $(OPT_LEVEL) $(C_FLAGS) 18 | $(GCC) -o $@ $<.o $(C_LIBS) $(OPT_LEVEL) $(DEBUG_FLAGS) 19 | 20 | %.cpp.out: %.cpp 21 | $(GCC) -o $<.o $< -c $(OPT_LEVEL) $(CPP_FLAGS) 22 | $(GCC) -o $@ $<.o $(CPP_LIBS) $(OPT_LEVEL) $(DEBUG_FLAGS) 23 | 24 | %.py.out: %.py 25 | cp $< $@ 26 | chmod +x $@ 27 | 28 | clean: 29 | rm -f *.o 30 | rm -f *.out 31 | rm -f *.llvm 32 | -------------------------------------------------------------------------------- /tests/PerfTests/FibRanges/args.in: -------------------------------------------------------------------------------- 1 | 70000 -------------------------------------------------------------------------------- /tests/PerfTests/FibRanges/fib_op.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | unsigned int fib(unsigned int n) { 5 | unsigned int a = 0; 6 | unsigned int b = 1; 7 | for ( int i=0; i 3 | 4 | using namespace std; 5 | 6 | unsigned long fib(unsigned long n) { 7 | unsigned long a = 0; 8 | unsigned long b = 1; 9 | for ( int i=0; i>>*/ 24 | -------------------------------------------------------------------------------- /tests/PerfTests/FibRanges/fib_op_base.spr: -------------------------------------------------------------------------------- 1 | // !! -O2 2 | 3 | import std.algorithms 4 | 5 | fun fib(n: Int): Int 6 | var a: Int = 0 7 | var b: Int = 1 8 | for i = 0..n 9 | var aOld = a 10 | a = b 11 | b += aOld 12 | return b 13 | 14 | fun sprMain 15 | if ( programArgs.size() < 2 ) 16 | return; 17 | let n = programArgs(1) asInt 18 | 19 | var res: Int = 0 20 | for i = 1...n 21 | let f = fib(i) 22 | if ( f % 2 != 0 ) 23 | res += f*f; 24 | ; 25 | cout << res << endl 26 | 27 | /*-<<>>*/ 29 | -------------------------------------------------------------------------------- /tests/PerfTests/FibRanges/programs.in: -------------------------------------------------------------------------------- 1 | ./fib_op.c.out 2 | ./fib_op.cpp.out 3 | ./fib_op.out 4 | ./fib_op_base.out -------------------------------------------------------------------------------- /tests/PerfTests/ForPerf/Makefile: -------------------------------------------------------------------------------- 1 | 2 | GCC=gcc 3 | OPT_LEVEL=-O2 4 | C_FLAGS= 5 | C_LIBS=-lc 6 | CPP_FLAGS=-std=c++11 7 | CPP_LIBS=-lc -lstdc++ 8 | 9 | SPARROWC=~/work/sparrow/dev/.out/Release/SparrowCompiler 10 | 11 | all: for.c.out for_pre.cpp.out for_post.cpp.out while.cpp.out for_ranges.cpp.out spr_for.spr.out spr_while.spr.out 12 | 13 | %.spr.out: %.spr 14 | $(SPARROWC) -o $@ $< $(OPT_LEVEL) $(DEBUG_FLAGS) 15 | 16 | %.c.out: %.c 17 | $(GCC) -o $<.o $< -c $(OPT_LEVEL) $(C_FLAGS) 18 | $(GCC) -o $@ $<.o $(C_LIBS) $(OPT_LEVEL) $(DEBUG_FLAGS) 19 | 20 | %.cpp.out: %.cpp 21 | $(GCC) -o $<.o $< -c $(OPT_LEVEL) $(CPP_FLAGS) 22 | $(GCC) -o $@ $<.o $(CPP_LIBS) $(OPT_LEVEL) $(DEBUG_FLAGS) 23 | 24 | %.py.out: %.py 25 | cp $< $@ 26 | chmod +x $@ 27 | 28 | clean: 29 | rm -f *.o 30 | rm -f *.out 31 | rm -f *.llvm 32 | -------------------------------------------------------------------------------- /tests/PerfTests/ForPerf/args.in: -------------------------------------------------------------------------------- 1 | 20000 2 | 50000 3 | 70000 -------------------------------------------------------------------------------- /tests/PerfTests/ForPerf/for.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | unsigned long testAccumulate(unsigned n) 5 | { 6 | unsigned long res = 0; 7 | for ( unsigned i=0; i 3 | 4 | using namespace std; 5 | 6 | unsigned long testAccumulate(unsigned n) 7 | { 8 | unsigned long res = 0; 9 | for ( unsigned i=0; i 3 | 4 | using namespace std; 5 | 6 | unsigned long testAccumulate(unsigned n) 7 | { 8 | unsigned long res = 0; 9 | for ( unsigned i=0; i>>*/ 22 | -------------------------------------------------------------------------------- /tests/PerfTests/ForPerf/spr_while.spr: -------------------------------------------------------------------------------- 1 | //!! -O2 2 | 3 | fun testAccumulate(n: UInt32): UInt64 4 | var res: UInt64 = 0 5 | var i = 0 6 | while i>>*/ 22 | -------------------------------------------------------------------------------- /tests/PerfTests/ForPerf/while.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | 4 | using namespace std; 5 | 6 | unsigned long testAccumulate(unsigned n) 7 | { 8 | unsigned long res = 0; 9 | unsigned i = 0; 10 | while ( i < n) 11 | { 12 | unsigned j = 0; 13 | while ( j < n) 14 | { 15 | res += i*j; 16 | ++j; 17 | } 18 | ++i; 19 | } 20 | return res; 21 | } 22 | 23 | int main(int argc, char** argv) 24 | { 25 | if ( argc < 2 ) 26 | return -1; 27 | unsigned n = atoi(argv[1]); 28 | 29 | unsigned long res = testAccumulate(n); 30 | cout << res << endl; 31 | 32 | return 0; 33 | } -------------------------------------------------------------------------------- /tests/PerfTests/GoogleBench/.gitignore: -------------------------------------------------------------------------------- 1 | orig 2 | -------------------------------------------------------------------------------- /tests/PerfTests/GoogleBench/Makefile: -------------------------------------------------------------------------------- 1 | 2 | GCC=clang 3 | OPT_LEVEL=-O2 4 | C_FLAGS= 5 | C_LIBS=-lc 6 | CPP_FLAGS=-std=c++11 7 | CPP_LIBS=-lc -lstdc++ 8 | 9 | SPARROWC=~/work/sparrow/dev/.out/Release/SparrowCompiler 10 | 11 | all: LoopTesterApp.spr.out 12 | $(MAKE) -C orig/cpp/ 13 | $(MAKE) -C orig/go/ 14 | $(MAKE) -C orig/java/ 15 | $(MAKE) -C orig/scala/ 16 | 17 | %.spr.out: %.spr 18 | $(SPARROWC) -o $@ $< $(OPT_LEVEL) $(DEBUG_FLAGS) 19 | 20 | %.c.out: %.c 21 | $(GCC) -o $<.o $< -c $(OPT_LEVEL) $(C_FLAGS) 22 | $(GCC) -o $@ $<.o $(C_LIBS) $(OPT_LEVEL) $(DEBUG_FLAGS) 23 | 24 | %.cpp.out: %.cpp 25 | $(GCC) -o $<.o $< -c $(OPT_LEVEL) $(CPP_FLAGS) 26 | $(GCC) -o $@ $<.o $(CPP_LIBS) $(OPT_LEVEL) $(DEBUG_FLAGS) 27 | 28 | %.py.out: %.py 29 | cp $< $@ 30 | chmod +x $@ 31 | 32 | clean: 33 | rm -f *.o 34 | rm -f *.out 35 | rm -f *.llvm 36 | $(MAKE) clean -C orig/cpp/ 37 | $(MAKE) clean -C orig/go/ 38 | $(MAKE) clean -C orig/java/ 39 | $(MAKE) clean -C orig/scala/ 40 | -------------------------------------------------------------------------------- /tests/PerfTests/GoogleBench/args.in: -------------------------------------------------------------------------------- 1 | 50 -------------------------------------------------------------------------------- /tests/PerfTests/GoogleBench/programs.in: -------------------------------------------------------------------------------- 1 | LoopTesterApp_Spr: ./LoopTesterApp.out 2 | LoopTesterApp_Cpp: orig/cpp/a.out 3 | LoopTesterApp_Go: orig/go/6.out 4 | LoopTesterApp_Java: java -server -Xss15500k -classpath orig/java LoopTesterApp 5 | LoopTesterApp_Scala: java -XX:+UseCompressedOops -server -Xss15500k -classpath /usr/local/Cellar/scala/2.11.2/libexec/lib/scala-library.jar:orig/scala LoopTesterApp 6 | -------------------------------------------------------------------------------- /tests/PerfTests/LazyRanges/Makefile: -------------------------------------------------------------------------------- 1 | 2 | GCC=clang 3 | OPT_LEVEL=-O2 4 | C_FLAGS= 5 | C_LIBS=-lc 6 | CPP_FLAGS=-std=c++11 7 | CPP_LIBS=-lc -lstdc++ 8 | 9 | SPARROWC=~/work/sparrow/dev/.out/Release/SparrowCompiler 10 | 11 | all: lazy_ranges.c.out lazy_ranges.cpp.out lazy_ranges_base.spr.out lazy_ranges.spr.out 12 | 13 | %.spr.out: %.spr 14 | $(SPARROWC) -o $@ $< $(OPT_LEVEL) $(DEBUG_FLAGS) 15 | 16 | %.c.out: %.c 17 | $(GCC) -o $<.o $< -c $(OPT_LEVEL) $(C_FLAGS) 18 | $(GCC) -o $@ $<.o $(C_LIBS) $(OPT_LEVEL) $(DEBUG_FLAGS) 19 | 20 | %.cpp.out: %.cpp 21 | $(GCC) -o $<.o $< -c $(OPT_LEVEL) $(CPP_FLAGS) 22 | $(GCC) -o $@ $<.o $(CPP_LIBS) $(OPT_LEVEL) $(DEBUG_FLAGS) 23 | 24 | %.py.out: %.py 25 | cp $< $@ 26 | chmod +x $@ 27 | 28 | clean: 29 | rm -f *.o 30 | rm -f *.out 31 | rm -f *.llvm 32 | -------------------------------------------------------------------------------- /tests/PerfTests/LazyRanges/args.in: -------------------------------------------------------------------------------- 1 | 600 -------------------------------------------------------------------------------- /tests/PerfTests/LazyRanges/lazy_ranges.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | 6 | unsigned long long nextCollatz(unsigned long long n) { return n%2==0 ? n/2 : n*3+1; } 7 | unsigned int collatzLen(unsigned long long n) 8 | { 9 | unsigned int len = 1; 10 | while ( n > 1 ) 11 | { 12 | n = nextCollatz(n); 13 | ++len; 14 | } 15 | return len; 16 | } 17 | 18 | int main(int argc, char** argv) 19 | { 20 | if ( argc < 2 ) 21 | return -1; 22 | unsigned n = atoi(argv[1]); 23 | 24 | unsigned long long sum = 0; 25 | int count = 0; 26 | for ( unsigned int i=1; ; ++i ) 27 | { 28 | unsigned int len = collatzLen(i); 29 | if ( len >= n ) 30 | break; 31 | // Main part of computing the root mean square 32 | sum += len*len; 33 | ++count; 34 | } 35 | double res = sqrt((double)(sum) / (double)(count)); 36 | printf("%f\n", res); 37 | 38 | return 0; 39 | } -------------------------------------------------------------------------------- /tests/PerfTests/LazyRanges/lazy_ranges.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | 5 | using namespace std; 6 | 7 | unsigned long long nextCollatz(unsigned long long n) { return n%2==0 ? n/2 : n*3+1; } 8 | unsigned int collatzLen(unsigned long long n) 9 | { 10 | unsigned int len = 1; 11 | while ( n > 1 ) 12 | { 13 | n = nextCollatz(n); 14 | ++len; 15 | } 16 | return len; 17 | } 18 | 19 | int main(int argc, char** argv) 20 | { 21 | if ( argc < 2 ) 22 | return -1; 23 | unsigned n = atoi(argv[1]); 24 | 25 | unsigned long long sum = 0; 26 | int count = 0; 27 | for ( unsigned int i=1; ; ++i ) 28 | { 29 | unsigned int len = collatzLen(i); 30 | if ( len >= n ) 31 | break; 32 | // Main part of computing the root mean square 33 | sum += len*len; 34 | ++count; 35 | } 36 | double res = sqrt(double(sum) / double(count)); 37 | cout << res << endl; 38 | 39 | return 0; 40 | } -------------------------------------------------------------------------------- /tests/PerfTests/LazyRanges/lazy_ranges.spr: -------------------------------------------------------------------------------- 1 | //!! -O2 2 | 3 | import std.algorithms 4 | import std.ranges 5 | import std.rMath 6 | 7 | fun nextCollatz(n: UInt64): UInt64 = ife(n%2UL==0UL, n/2UL, n*3UL+1UL) 8 | fun collatzSeq(n: Int) = generate1(UInt64(n), \nextCollatz) takeUntil (fun n = n==1UL) 9 | 10 | fun toU64 n = UInt64(n) 11 | 12 | fun sprMain 13 | if ( programArgs.size() < 2 ) 14 | return; 15 | let n = programArgs(1) asInt 16 | 17 | let res = (1..) map \collatzSeq map \rangeSize takeWhile (fun.{n} s = s < n) map \toU64 rootMeanSquare 18 | cout << res << endl 19 | 20 | /*<<>>*/ 23 | /*<<>>*/ 26 | -------------------------------------------------------------------------------- /tests/PerfTests/LazyRanges/lazy_ranges_base.spr: -------------------------------------------------------------------------------- 1 | //!! -O2 2 | 3 | import std.algorithms 4 | import std.ranges 5 | import math 6 | 7 | fun nextCollatz n = ife(n%2==0, n/2, n*3+1) 8 | 9 | fun collatzLen(n: UInt64): UInt32 10 | var len = UInt32(1) 11 | while n > 1 12 | n = nextCollatz(n) 13 | ++len 14 | return len 15 | 16 | fun sprMain 17 | if ( programArgs.size() < 2 ) 18 | return; 19 | let n = programArgs(1) asInt 20 | 21 | var sum: UInt64 = 0 22 | var count = 0 23 | for i = 1.. 24 | let len = collatzLen(i) 25 | if ( len >= n ) 26 | break; 27 | // Main part of computing the root mean square 28 | sum += len*len 29 | ++count 30 | let res = sqrt(Float(sum) / Float(count)) 31 | cout << res << endl 32 | 33 | /*<<>>*/ 36 | /*<<>>*/ 39 | -------------------------------------------------------------------------------- /tests/PerfTests/LazyRanges/programs.in: -------------------------------------------------------------------------------- 1 | C: ./lazy_ranges.c.out 2 | C++: ./lazy_ranges.cpp.out 3 | Spr classic:./lazy_ranges_base.out 4 | Spr ranges: ./lazy_ranges.out 5 | -------------------------------------------------------------------------------- /tests/Simple/Ackermann.spr: -------------------------------------------------------------------------------- 1 | //!! -t "../Basic/SparrowImplicitLib.spr" -fno-main 2 | fun ackermann(m, n: Int): Int 3 | if ( m == 0 ) 4 | return n + 1 5 | if ( m > 0 && n == 0 ) 6 | return ackermann(m - 1, 1) 7 | return ackermann(m - 1, ackermann(m, n - 1)) 8 | 9 | [native("test")] fun test(n: Int) 10 | writeLnInt(ackermann(0, 0)) 11 | writeLnInt(ackermann(0, 1)) 12 | writeLnInt(ackermann(0, 2)) 13 | writeLnInt(ackermann(0, 3)) 14 | writeLnInt(ackermann(0, 4)) 15 | write('\n') 16 | writeLnInt(ackermann(1, 0)) 17 | writeLnInt(ackermann(1, 1)) 18 | writeLnInt(ackermann(1, 2)) 19 | writeLnInt(ackermann(1, 3)) 20 | writeLnInt(ackermann(1, 4)) 21 | write('\n') 22 | writeLnInt(ackermann(2, 0)) 23 | writeLnInt(ackermann(2, 1)) 24 | writeLnInt(ackermann(2, 2)) 25 | writeLnInt(ackermann(2, 3)) 26 | writeLnInt(ackermann(2, 4)) 27 | write('\n') 28 | writeLnInt(ackermann(3, 0)) 29 | writeLnInt(ackermann(3, 1)) 30 | writeLnInt(ackermann(3, 2)) 31 | writeLnInt(ackermann(3, 3)) 32 | writeLnInt(ackermann(3, 4)) 33 | write('\n') 34 | writeLnInt(ackermann(4, 0)) 35 | 36 | /*<<>>*/ 63 | -------------------------------------------------------------------------------- /tests/Simple/Factorization.spr: -------------------------------------------------------------------------------- 1 | //!! -t "../Basic/SparrowImplicitLib.spr" -fno-main 2 | fun factor(n: Int) 3 | if ( n < 1 ) 4 | write('T'); write('R'); write('O'); write('L'); writeLn('L') 5 | return 6 | 7 | var i: Int 8 | i = 2 9 | 10 | while n != 1 11 | while n % i != 0 12 | i = i + 1 13 | 14 | var j: Int 15 | j = 0 16 | 17 | while n % i == 0 18 | j = j + 1 19 | n = n / i 20 | 21 | write(i) 22 | write(' ') 23 | write('^') 24 | write(' ') 25 | write(j) 26 | if ( n != 1 ) 27 | write(' ') 28 | write('*') 29 | write(' ') 30 | write('\n') 31 | 32 | [native("test")] fun test(n: Int) 33 | factor(2) 34 | factor(60) 35 | factor(541) 36 | factor(1024) 37 | factor(10080) 38 | factor(10201) 39 | factor(287699987) 40 | 41 | /*<<>>*/ 50 | -------------------------------------------------------------------------------- /tests/Simple/Fibonacci.spr: -------------------------------------------------------------------------------- 1 | //!! -t "../Basic/SparrowImplicitLib.spr" -fno-main 2 | fun fibonacciRecursive(n: Int): Int 3 | if ( n == 0 || n == 1 ) 4 | return 1 5 | 6 | return fibonacciRecursive(n - 1) + fibonacciRecursive(n - 2) 7 | 8 | fun fibonacciIterative(n: Int): Int 9 | if ( n == 0 || n == 1 ) 10 | return 1 11 | 12 | var a, b, i, t: Int 13 | a = 1 14 | b = 1 15 | i = 2 16 | 17 | while i <= n ; i = i + 1 18 | t = a + b 19 | a = b 20 | b = t 21 | 22 | return b 23 | 24 | [native("test")] fun test(n: Int) 25 | writeLnInt(fibonacciRecursive(0)) 26 | writeLnInt(fibonacciRecursive(1)) 27 | writeLnInt(fibonacciRecursive(5)) 28 | writeLnInt(fibonacciRecursive(15)) 29 | writeLnInt(fibonacciRecursive(30)) 30 | 31 | writeLnInt(fibonacciIterative(0)) 32 | writeLnInt(fibonacciIterative(1)) 33 | writeLnInt(fibonacciIterative(5)) 34 | writeLnInt(fibonacciIterative(15)) 35 | writeLnInt(fibonacciIterative(30)) 36 | 37 | /*<<>>*/ 49 | -------------------------------------------------------------------------------- /tests/Simple/GCD.spr: -------------------------------------------------------------------------------- 1 | //!! -t "../Basic/SparrowImplicitLib.spr" -fno-main 2 | fun gcdDivision(a: Int, b: Int): Int 3 | var t: Int 4 | 5 | while b != 0 6 | t = b 7 | b = a % b 8 | a = t 9 | 10 | return a 11 | 12 | fun gcdSubtraction(a: Int, b: Int): Int 13 | if ( a == 0 ) 14 | return b 15 | 16 | while b != 0 17 | if ( a > b ) 18 | a = a - b 19 | else 20 | b = b - a 21 | 22 | return a 23 | 24 | [native("test")] fun test(n: Int) 25 | writeLnInt(gcdDivision(60, 42)) 26 | writeLnInt(gcdDivision(2346, 13556)) 27 | writeLnInt(gcdDivision(8769534, 481263)) 28 | 29 | writeLnInt(gcdSubtraction(60, 42)) 30 | writeLnInt(gcdSubtraction(2346, 13556)) 31 | writeLnInt(gcdSubtraction(8769534, 481263)) 32 | 33 | /*<<>>*/ 41 | -------------------------------------------------------------------------------- /tests/Simple/Primality.spr: -------------------------------------------------------------------------------- 1 | //!! -t "../Basic/SparrowImplicitLib.spr" -fno-main 2 | fun assert(b: Bool) 3 | if ( !b ) 4 | write('F'); write('A'); write('I'); writeLn('L') 5 | 6 | fun fassert(b: Bool) 7 | if ( ! !b ) 8 | write('F'); write('A'); write('I'); writeLn('L') 9 | 10 | fun isPrime(n: Int): Bool 11 | if ( n < 2 ) 12 | return false 13 | if ( n == 2 ) 14 | return true 15 | if ( n % 2 == 0 ) 16 | return false 17 | 18 | var i: Int 19 | i = 3 20 | 21 | while i * i <= n ; i = i + 1 22 | if ( n % i == 0 ) 23 | return false 24 | 25 | return true 26 | 27 | [native("test")] fun test(n: Int) 28 | fassert(isPrime(0)) 29 | fassert(isPrime(1)) 30 | assert(isPrime(2)) 31 | assert(isPrime(3)) 32 | fassert(isPrime(4)) 33 | assert(isPrime(5)) 34 | fassert(isPrime(6)) 35 | assert(isPrime(7)) 36 | fassert(isPrime(8)) 37 | fassert(isPrime(9)) 38 | assert(isPrime(541)) 39 | assert(isPrime(104729)) 40 | assert(isPrime(15485863)) 41 | fassert(isPrime(4972331)) 42 | 43 | write('O'); writeLn('K') 44 | 45 | /*<<>>*/ 48 | -------------------------------------------------------------------------------- /tests/Simple/SecantMethod.spr: -------------------------------------------------------------------------------- 1 | //!! -t "../Basic/SparrowImplicitLib.spr" -fno-main 2 | fun abs(x: Float): Float 3 | if ( x < 0.0 ) 4 | return -x 5 | else 6 | return x 7 | 8 | fun poly3(a, b, c, d, x: Float): Float 9 | return a * x * x * x + b * x * x + c * x + d 10 | 11 | fun secantMethod(a, b, c, d, x1, x2, err: Float): Float 12 | var t, p1, p2: Float 13 | 14 | while abs(poly3(a, b, c, d, x2)) > err 15 | p2 = poly3(a, b, c, d, x2) 16 | p1 = poly3(a, b, c, d, x1) 17 | t = x2 - p2 * (x2 - x1) / (p2 - p1) 18 | x1 = x2 19 | x2 = t 20 | 21 | return t 22 | 23 | [native("test")] fun test(n: Int) 24 | writeLnFloat(secantMethod(0.0, 1.0, 0.0, -612.0, 10.0, 30.0, 0.001)) 25 | writeLnFloat(secantMethod(1.0, 2.0, 3.0, 4.0, -10.0, 10.0, 0.00001)) 26 | 27 | /*<<>>*/ 31 | -------------------------------------------------------------------------------- /tests/StdLib/StringOperators.spr: -------------------------------------------------------------------------------- 1 | //!! 2 | 3 | fun sprMain 4 | // test for string '=' operator 5 | var string1: StringRef = "first string" 6 | cout << string1 << endl // first string 7 | 8 | var string2: StringRef = "second string" 9 | 10 | string1 = string2 11 | cout << string1 << endl // second string 12 | 13 | // test for string '+ (StringRef, StringRef)' operator 14 | var ana: StringRef = "ana" 15 | var are: StringRef = " are" 16 | ana = ana + are 17 | cout << ana << endl // "ana are" 18 | 19 | // test for string '+ (StringRef, Char)' operator 20 | var c1, c2, c3, c4, c5: Char 21 | c1 = ' '.char 22 | c2 = 'm'.char 23 | c3 = 'e'.char 24 | c4 = 'r'.char 25 | c5 = 'e'.char 26 | ana = ana + c1 27 | ana = ana + c2 28 | ana = ana + c3 29 | ana = ana + c4 30 | ana = ana + c5 31 | cout << ana << endl // "ana are mere" 32 | 33 | /*<<>>*/ -------------------------------------------------------------------------------- /tools/formatDetails/tokenData.spr: -------------------------------------------------------------------------------- 1 | //! Defines the TokenData and TokenVector datatypes 2 | module formatTool.formatDetails.tokenData 3 | 4 | import token, node 5 | import meta.location 6 | import std.vector 7 | 8 | //! The data used to represents the tokens of the program 9 | //! Contains complete information of the source code, and can be used at source-code transformations 10 | [initCtor] 11 | datatype TokenData 12 | type: TokenType 13 | loc: Location 14 | content: StringRef 15 | parentAst: Node 16 | canFormat: Bool = true 17 | 18 | //! A vector of tokens 19 | using TokenVector = TokenData Vector -------------------------------------------------------------------------------- /tools/transforms/defaultFormat.spr: -------------------------------------------------------------------------------- 1 | module formatTool.transforms.defaultFormat 2 | 3 | import formatDetails.sourceData 4 | 5 | fun defaultFormat(src: @SourceData) 6 | for token: @TokenData = src.tokens.all 7 | if !token.canFormat 8 | continue 9 | if token.type == tkWHITESPACE && token.content.size > 2 && token.loc.start.col > 1 10 | token.content = " " 11 | -------------------------------------------------------------------------------- /tools/transforms/emptyTransform.spr: -------------------------------------------------------------------------------- 1 | module formatTool.transforms.emptyTransform 2 | 3 | import formatDetails.sourceData 4 | 5 | fun emptyTransform(src: !SourceData) 6 | ; 7 | 8 | -------------------------------------------------------------------------------- /tools/transforms/refToMut.spr: -------------------------------------------------------------------------------- 1 | module formatTool.transforms.refToMut 2 | 3 | import formatDetails.sourceData 4 | 5 | fun refToMut(src: !SourceData) 6 | if src.tokens.size < 3 7 | return 8 | var prev2: @TokenData = src.tokens(0) 9 | var prev1: @TokenData = src.tokens(0) 10 | var cur: @TokenData = src.tokens(0) 11 | for i = 3..src.tokens.size 12 | if cur.type != tkWHITESPACE 13 | prev2 := prev1 14 | prev1 := cur 15 | cur := src.tokens(i) 16 | if !cur.canFormat 17 | continue 18 | if cur.type == tkOPERATOR && cur.content == '@' && prev1.type == tkCOLON && (prev2.parentAst kind) == nkParameter 19 | cur.content = '!' 20 | -------------------------------------------------------------------------------- /tools/transforms/removeExtraSpaces.spr: -------------------------------------------------------------------------------- 1 | module formatTool.transforms.removeExtraSpaces 2 | 3 | import utils 4 | import formatDetails.sourceData 5 | 6 | fun removeExtraSpaces(src: !SourceData) 7 | _removeEndSpaces(src) 8 | _removeMultipleEmptyLines(src) 9 | 10 | //! Remove spaces at the end of the line 11 | fun _removeEndSpaces(src: !SourceData) 12 | for i = 0..Int(src.tokens.size) 13 | var tok: @TokenData = src.tokens(i) 14 | var remaining = src.tokens.subrange(i+1) 15 | if tok.canFormat && tok.type == tkWHITESPACE && tok.content.size > 0 \ 16 | && nextIsNewline(remaining, false) 17 | tok.content = '' 18 | 19 | //! Remove multiple consecutive empty lines 20 | fun _removeMultipleEmptyLines(src: !SourceData) 21 | var lastLineWithVisible = 0 22 | var numNewlines = 0 23 | for i = 0..Int(src.tokens.size) 24 | var tok: @TokenData = src.tokens(i) 25 | var remaining = src.tokens.subrange(i+1) 26 | 27 | if tok.type != tkWHITESPACE && tok.type != tkEOL 28 | lastLineWithVisible = Int(tok.loc.start.line) 29 | numNewlines = 0 30 | if tok.type == tkEOL 31 | if lastLineWithVisible != Int(tok.loc.start.line) 32 | numNewlines++ 33 | 34 | if numNewlines >= 3 && tok.canFormat 35 | clearToken(tok) 36 | -------------------------------------------------------------------------------- /unittests/Common/BackendMock.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Nest/Api/Backend.h" 4 | #include "Nest/Utils/cppif/Fwd.hpp" 5 | 6 | using Nest::TypeRef; 7 | using Nest::Node; 8 | 9 | 10 | struct BackendMock : Nest_Backend 11 | { 12 | public: 13 | BackendMock(); 14 | ~BackendMock(); 15 | 16 | private: 17 | static void Init(Nest_Backend* backend, const char* mainFilename); 18 | static void GenerateMachineCode(Nest_Backend* backend, const Nest_SourceCode* code); 19 | static void Link(Nest_Backend* backend, const char* outFilename); 20 | static void CtProcess(Nest_Backend* backend, Node* node); 21 | static Node* CtEvaluate(Nest_Backend* backend, Node* node); 22 | static unsigned int SizeOf(Nest_Backend* backend, TypeRef type); 23 | static unsigned int AlignmentOf(Nest_Backend* backend, TypeRef type); 24 | static void CtApiRegisterFun(Nest_Backend* backend, const char* name, void* funPtr); 25 | }; -------------------------------------------------------------------------------- /unittests/Common/LocationGen.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Feather/Utils/cppif/FeatherNodes.hpp" 4 | 5 | using LocationGenFun = std::function; 6 | 7 | //! A generator for locations -- set by the fixture 8 | extern LocationGenFun g_LocationGen; -------------------------------------------------------------------------------- /unittests/Common/RcBasic.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Nest/Api/EvalMode.h" 4 | 5 | namespace rc { 6 | 7 | //! Arbitrary definition for EvalMode; can generate RT and CT modes values 8 | template <> struct Arbitrary { 9 | static Gen arbitrary() { return gen::element(modeRt, modeCt); } 10 | }; 11 | 12 | } // namespace rc 13 | -------------------------------------------------------------------------------- /unittests/Nest/MockType.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Nest/Utils/cppif/Type.hpp" 4 | 5 | //! Mock type that we can use in our unit-tests 6 | struct MockType : Nest::Type { 7 | //! Registers this type 8 | static void registerType(); 9 | 10 | //! Gets the type corresponding to the given parameters 11 | static MockType get(bool hasStorage, int numRefs, Nest::EvalMode mode); 12 | 13 | MockType() = default; 14 | MockType(Nest::TypeRef type); 15 | 16 | //! Returns a new type with the given mode, and the rest of parameters the same 17 | MockType changeMode(Nest::EvalMode newMode, Nest::Location loc = Nest::Location{}) const; 18 | 19 | private: 20 | //! The kind of this type; initialized after a call to registerType() 21 | static int typeKind; 22 | }; 23 | 24 | 25 | ostream& operator<<(ostream& os, MockType t); 26 | 27 | //! Returns a generator for our mock type 28 | rc::Gen arbMockType(); 29 | 30 | namespace rc { 31 | 32 | //! Helper to make RapidCheck generate arbitrary types 33 | template <> struct Arbitrary { 34 | static Gen arbitrary() { return arbMockType(); } 35 | }; 36 | 37 | } // namespace rc 38 | -------------------------------------------------------------------------------- /unittests/SparrowFrontend/SprCommon/ConceptsServiceMock.cpp: -------------------------------------------------------------------------------- 1 | #include "StdInc.h" 2 | #include "ConceptsServiceMock.hpp" 3 | 4 | #include "SparrowFrontend/SparrowFrontendTypes.hpp" 5 | 6 | #include "Feather/Utils/cppif/FeatherTypes.hpp" 7 | 8 | bool ConceptsServiceMock::conceptIsFulfilled(ConceptDecl concept, Type type) { 9 | for (auto p : conceptFulfillments_) 10 | if (p.first == concept && p.second.referredNode() == type.referredNode()) 11 | return true; 12 | return false; 13 | } 14 | bool ConceptsServiceMock::typeGeneratedFromGeneric(GenericDatatype genericDatatype, Type type) { 15 | return false; 16 | } 17 | ConceptType ConceptsServiceMock::baseConceptType(ConceptDecl concept) { 18 | for (auto p : baseConcepts_) 19 | if (p.first == concept) 20 | return p.second; 21 | return nullptr; 22 | } 23 | -------------------------------------------------------------------------------- /unittests/SparrowFrontend/SprCommon/ConceptsServiceMock.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "SparrowFrontend/Services/IConceptsService.h" 4 | 5 | using Nest::NodeHandle; 6 | using Nest::Type; 7 | using SprFrontend::ConceptDecl; 8 | using SprFrontend::ConceptType; 9 | using SprFrontend::GenericDatatype; 10 | 11 | struct ConceptsServiceMock : SprFrontend::IConceptsService { 12 | bool conceptIsFulfilled(ConceptDecl concept, Type type) final; 13 | bool typeGeneratedFromGeneric(GenericDatatype genericDatatype, Type type) final; 14 | ConceptType baseConceptType(ConceptDecl concept) final; 15 | 16 | vector> conceptFulfillments_; 17 | vector> baseConcepts_; // concept -> base concept type 18 | }; 19 | -------------------------------------------------------------------------------- /unittests/SparrowFrontend/SprCommon/GenValueForType.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Nest/Utils/cppif/TypeWithStorage.hpp" 4 | #include "Nest/Utils/cppif/NodeHandle.hpp" 5 | 6 | struct SampleTypes; 7 | 8 | 9 | //! Generator for arbitrary values for the given type. 10 | //! The type of the value matches perfectly the given type 11 | rc::Gen arbValueForType( 12 | Nest::TypeWithStorage t, const SampleTypes* sampleTypes = nullptr); 13 | 14 | //! Generator for arbitrary values for the given type (ignoring mode). 15 | //! Ignoring the mode, the type of the generated values matches the given type 16 | rc::Gen arbValueForTypeIgnoreMode(Nest::TypeWithStorage t); 17 | 18 | //! Generator of values that is convertible to the given type. 19 | rc::Gen arbValueConvertibleTo( 20 | Nest::TypeWithStorage t, const SampleTypes* sampleTypes = nullptr); 21 | 22 | //! Given a CT type or a Concept type, this return a generator of bound values for the type 23 | //! The returned values will always be CT. For concepts we generate a type node. 24 | rc::Gen arbBoundValueForType(Nest::TypeWithStorage t, const SampleTypes& sampleTypes); 25 | -------------------------------------------------------------------------------- /unittests/SparrowFrontend/SprCommon/OverloadServiceMock.cpp: -------------------------------------------------------------------------------- 1 | #include "StdInc.h" 2 | #include "OverloadServiceMock.hpp" 3 | 4 | #include "Feather/Utils/cppif/FeatherNodes.hpp" 5 | 6 | Node* OverloadServiceMock::selectOverload(CompilationContext* context, const Location& loc, 7 | EvalMode evalMode, Nest_NodeRange decls, Nest_NodeRange args, 8 | SprFrontend::OverloadReporting errReporting, Nest::StringRef funName) { 9 | return nullptr; 10 | } 11 | 12 | bool OverloadServiceMock::selectConversionCtor( 13 | CompilationContext* context, Node* destClass, EvalMode destMode, Nest::Type argType) { 14 | if (argType.mode() != destMode) 15 | return false; 16 | // If we know about the conversion, we return true 17 | Nest::Type destType = Feather::DataType::get(destClass, destMode); 18 | for (const auto& p : implicitConversions_) { 19 | if (p.first == argType && p.second == destType) 20 | return true; 21 | } 22 | return false; 23 | } 24 | 25 | Node* OverloadServiceMock::selectCtToRtCtor(Node* ctArg) { return nullptr; } 26 | -------------------------------------------------------------------------------- /unittests/SparrowFrontend/SprCommon/OverloadServiceMock.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "SparrowFrontend/Services/IOverloadService.h" 4 | 5 | #include "Nest/Utils/cppif/StringRef.hpp" 6 | 7 | using Nest::Node; 8 | using Nest::Location; 9 | using Nest::CompilationContext; 10 | 11 | struct OverloadServiceMock : SprFrontend::IOverloadService { 12 | Node* selectOverload(CompilationContext* context, const Location& loc, EvalMode evalMode, 13 | Nest_NodeRange decls, Nest_NodeRange args, SprFrontend::OverloadReporting errReporting, 14 | Nest::StringRef funName) final; 15 | 16 | bool selectConversionCtor(CompilationContext* context, Node* destClass, EvalMode destMode, 17 | Nest::Type argType) final; 18 | 19 | Node* selectCtToRtCtor(Node* ctArg) final; 20 | 21 | vector> implicitConversions_; 22 | }; 23 | -------------------------------------------------------------------------------- /unittests/SparrowFrontend/SprCommon/Utils.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Common/TypeFactory.hpp" 4 | 5 | using Feather::TypeWithStorage; 6 | 7 | //! Builds a string from a string prefix and an integer 8 | inline std::string concat(const char* prefix, int num) { 9 | ostringstream oss; 10 | oss << prefix << num; 11 | return oss.str(); 12 | } 13 | 14 | //! Generates a random boolean, given its 'true' probability 15 | inline bool randomChance(int percentage) { return *rc::gen::inRange(0, 100) < percentage; } 16 | -------------------------------------------------------------------------------- /unittests/StdInc.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "Nest/Utils/DefaultStdInc.hpp" 4 | #include "Nest/Utils/cppif/Fwd.hpp" 5 | 6 | #define CATCH_CONFIG_FAST_COMPILE 7 | #include "rapidcheck.h" 8 | #include "rapidcheck/catch.h" 9 | -------------------------------------------------------------------------------- /unittests/UnitTestsMain.cpp: -------------------------------------------------------------------------------- 1 | #define CATCH_CONFIG_MAIN 2 | #include 3 | --------------------------------------------------------------------------------