├── .clang-format ├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ ├── config.yml │ └── feature_request.md ├── codecov.yml └── workflows │ ├── benchmark.yml │ ├── build.yml │ ├── new-release.yml │ └── release.yml ├── .gitignore ├── Analysis ├── include │ └── Luau │ │ ├── Anyification.h │ │ ├── ApplyTypeFunction.h │ │ ├── AstJsonEncoder.h │ │ ├── AstQuery.h │ │ ├── Autocomplete.h │ │ ├── AutocompleteTypes.h │ │ ├── BuiltinDefinitions.h │ │ ├── Cancellation.h │ │ ├── Clone.h │ │ ├── Constraint.h │ │ ├── ConstraintGenerator.h │ │ ├── ConstraintSet.h │ │ ├── ConstraintSolver.h │ │ ├── ControlFlow.h │ │ ├── DataFlowGraph.h │ │ ├── DcrLogger.h │ │ ├── Def.h │ │ ├── Differ.h │ │ ├── Documentation.h │ │ ├── EqSatSimplification.h │ │ ├── EqSatSimplificationImpl.h │ │ ├── Error.h │ │ ├── ExpectedTypeVisitor.h │ │ ├── FileResolver.h │ │ ├── FragmentAutocomplete.h │ │ ├── Frontend.h │ │ ├── Generalization.h │ │ ├── GlobalTypes.h │ │ ├── InferPolarity.h │ │ ├── InsertionOrderedMap.h │ │ ├── Instantiation.h │ │ ├── Instantiation2.h │ │ ├── IostreamHelpers.h │ │ ├── JsonEmitter.h │ │ ├── LValue.h │ │ ├── Linter.h │ │ ├── Metamethods.h │ │ ├── Module.h │ │ ├── ModuleResolver.h │ │ ├── NonStrictTypeChecker.h │ │ ├── Normalize.h │ │ ├── NotNull.h │ │ ├── OverloadResolution.h │ │ ├── Polarity.h │ │ ├── Predicate.h │ │ ├── Quantify.h │ │ ├── RecursionCounter.h │ │ ├── Refinement.h │ │ ├── RequireTracer.h │ │ ├── Scope.h │ │ ├── Set.h │ │ ├── Simplify.h │ │ ├── Substitution.h │ │ ├── Subtyping.h │ │ ├── Symbol.h │ │ ├── TableLiteralInference.h │ │ ├── ToDot.h │ │ ├── ToString.h │ │ ├── TopoSortStatements.h │ │ ├── Transpiler.h │ │ ├── TxnLog.h │ │ ├── Type.h │ │ ├── TypeArena.h │ │ ├── TypeAttach.h │ │ ├── TypeCheckLimits.h │ │ ├── TypeChecker2.h │ │ ├── TypeFunction.h │ │ ├── TypeFunctionReductionGuesser.h │ │ ├── TypeFunctionRuntime.h │ │ ├── TypeFunctionRuntimeBuilder.h │ │ ├── TypeFwd.h │ │ ├── TypeIds.h │ │ ├── TypeInfer.h │ │ ├── TypeOrPack.h │ │ ├── TypePack.h │ │ ├── TypePairHash.h │ │ ├── TypePath.h │ │ ├── TypeUtils.h │ │ ├── TypedAllocator.h │ │ ├── Unifiable.h │ │ ├── Unifier.h │ │ ├── Unifier2.h │ │ ├── UnifierSharedState.h │ │ └── VisitType.h └── src │ ├── Anyification.cpp │ ├── ApplyTypeFunction.cpp │ ├── AstJsonEncoder.cpp │ ├── AstQuery.cpp │ ├── Autocomplete.cpp │ ├── AutocompleteCore.cpp │ ├── AutocompleteCore.h │ ├── BuiltinDefinitions.cpp │ ├── Clone.cpp │ ├── Constraint.cpp │ ├── ConstraintGenerator.cpp │ ├── ConstraintSolver.cpp │ ├── DataFlowGraph.cpp │ ├── DcrLogger.cpp │ ├── Def.cpp │ ├── Differ.cpp │ ├── EmbeddedBuiltinDefinitions.cpp │ ├── EqSatSimplification.cpp │ ├── Error.cpp │ ├── ExpectedTypeVisitor.cpp │ ├── FileResolver.cpp │ ├── FragmentAutocomplete.cpp │ ├── Frontend.cpp │ ├── Generalization.cpp │ ├── GlobalTypes.cpp │ ├── InferPolarity.cpp │ ├── Instantiation.cpp │ ├── Instantiation2.cpp │ ├── IostreamHelpers.cpp │ ├── JsonEmitter.cpp │ ├── LValue.cpp │ ├── Linter.cpp │ ├── Module.cpp │ ├── NonStrictTypeChecker.cpp │ ├── Normalize.cpp │ ├── OverloadResolution.cpp │ ├── Quantify.cpp │ ├── Refinement.cpp │ ├── RequireTracer.cpp │ ├── Scope.cpp │ ├── Simplify.cpp │ ├── Substitution.cpp │ ├── Subtyping.cpp │ ├── Symbol.cpp │ ├── TableLiteralInference.cpp │ ├── ToDot.cpp │ ├── ToString.cpp │ ├── TopoSortStatements.cpp │ ├── Transpiler.cpp │ ├── TxnLog.cpp │ ├── Type.cpp │ ├── TypeArena.cpp │ ├── TypeAttach.cpp │ ├── TypeChecker2.cpp │ ├── TypeFunction.cpp │ ├── TypeFunctionReductionGuesser.cpp │ ├── TypeFunctionRuntime.cpp │ ├── TypeFunctionRuntimeBuilder.cpp │ ├── TypeIds.cpp │ ├── TypeInfer.cpp │ ├── TypeOrPack.cpp │ ├── TypePack.cpp │ ├── TypePath.cpp │ ├── TypeUtils.cpp │ ├── TypedAllocator.cpp │ ├── Unifiable.cpp │ ├── Unifier.cpp │ └── Unifier2.cpp ├── Ast ├── include │ └── Luau │ │ ├── Allocator.h │ │ ├── Ast.h │ │ ├── Confusables.h │ │ ├── Cst.h │ │ ├── Lexer.h │ │ ├── Location.h │ │ ├── ParseOptions.h │ │ ├── ParseResult.h │ │ ├── Parser.h │ │ ├── StringUtils.h │ │ └── TimeTrace.h └── src │ ├── Allocator.cpp │ ├── Ast.cpp │ ├── Confusables.cpp │ ├── Cst.cpp │ ├── Lexer.cpp │ ├── Location.cpp │ ├── Parser.cpp │ ├── StringUtils.cpp │ └── TimeTrace.cpp ├── CLI ├── include │ └── Luau │ │ ├── AnalyzeRequirer.h │ │ ├── Coverage.h │ │ ├── FileUtils.h │ │ ├── Flags.h │ │ ├── Profiler.h │ │ ├── Repl.h │ │ ├── ReplRequirer.h │ │ └── VfsNavigator.h └── src │ ├── Analyze.cpp │ ├── AnalyzeRequirer.cpp │ ├── Ast.cpp │ ├── Bytecode.cpp │ ├── Compile.cpp │ ├── Coverage.cpp │ ├── FileUtils.cpp │ ├── Flags.cpp │ ├── Profiler.cpp │ ├── Reduce.cpp │ ├── Repl.cpp │ ├── ReplEntry.cpp │ ├── ReplRequirer.cpp │ ├── VfsNavigator.cpp │ └── Web.cpp ├── CMakeLists.txt ├── CMakePresets.json ├── CONTRIBUTING.md ├── CodeGen ├── include │ ├── Luau │ │ ├── AddressA64.h │ │ ├── AssemblyBuilderA64.h │ │ ├── AssemblyBuilderX64.h │ │ ├── BytecodeAnalysis.h │ │ ├── BytecodeSummary.h │ │ ├── CodeAllocator.h │ │ ├── CodeBlockUnwind.h │ │ ├── CodeGen.h │ │ ├── CodeGenCommon.h │ │ ├── CodeGenOptions.h │ │ ├── ConditionA64.h │ │ ├── ConditionX64.h │ │ ├── IrAnalysis.h │ │ ├── IrBuilder.h │ │ ├── IrCallWrapperX64.h │ │ ├── IrData.h │ │ ├── IrDump.h │ │ ├── IrRegAllocX64.h │ │ ├── IrUtils.h │ │ ├── IrVisitUseDef.h │ │ ├── Label.h │ │ ├── LoweringStats.h │ │ ├── NativeProtoExecData.h │ │ ├── OperandX64.h │ │ ├── OptimizeConstProp.h │ │ ├── OptimizeDeadStore.h │ │ ├── OptimizeFinalX64.h │ │ ├── RegisterA64.h │ │ ├── RegisterX64.h │ │ ├── SharedCodeAllocator.h │ │ ├── UnwindBuilder.h │ │ ├── UnwindBuilderDwarf2.h │ │ └── UnwindBuilderWin.h │ └── luacodegen.h └── src │ ├── AssemblyBuilderA64.cpp │ ├── AssemblyBuilderX64.cpp │ ├── BitUtils.h │ ├── ByteUtils.h │ ├── BytecodeAnalysis.cpp │ ├── BytecodeSummary.cpp │ ├── CodeAllocator.cpp │ ├── CodeBlockUnwind.cpp │ ├── CodeGen.cpp │ ├── CodeGenA64.cpp │ ├── CodeGenA64.h │ ├── CodeGenAssembly.cpp │ ├── CodeGenContext.cpp │ ├── CodeGenContext.h │ ├── CodeGenLower.h │ ├── CodeGenUtils.cpp │ ├── CodeGenUtils.h │ ├── CodeGenX64.cpp │ ├── CodeGenX64.h │ ├── EmitBuiltinsX64.cpp │ ├── EmitBuiltinsX64.h │ ├── EmitCommon.h │ ├── EmitCommonA64.h │ ├── EmitCommonX64.cpp │ ├── EmitCommonX64.h │ ├── EmitInstructionX64.cpp │ ├── EmitInstructionX64.h │ ├── IrAnalysis.cpp │ ├── IrBuilder.cpp │ ├── IrCallWrapperX64.cpp │ ├── IrDump.cpp │ ├── IrLoweringA64.cpp │ ├── IrLoweringA64.h │ ├── IrLoweringX64.cpp │ ├── IrLoweringX64.h │ ├── IrRegAllocA64.cpp │ ├── IrRegAllocA64.h │ ├── IrRegAllocX64.cpp │ ├── IrTranslateBuiltins.cpp │ ├── IrTranslateBuiltins.h │ ├── IrTranslation.cpp │ ├── IrTranslation.h │ ├── IrUtils.cpp │ ├── IrValueLocationTracking.cpp │ ├── IrValueLocationTracking.h │ ├── NativeProtoExecData.cpp │ ├── NativeState.cpp │ ├── NativeState.h │ ├── OptimizeConstProp.cpp │ ├── OptimizeDeadStore.cpp │ ├── OptimizeFinalX64.cpp │ ├── SharedCodeAllocator.cpp │ ├── UnwindBuilderDwarf2.cpp │ ├── UnwindBuilderWin.cpp │ └── lcodegen.cpp ├── Common └── include │ └── Luau │ ├── Bytecode.h │ ├── BytecodeUtils.h │ ├── Common.h │ ├── DenseHash.h │ ├── ExperimentalFlags.h │ ├── Variant.h │ └── VecDeque.h ├── Compiler ├── include │ ├── Luau │ │ ├── BytecodeBuilder.h │ │ └── Compiler.h │ └── luacode.h └── src │ ├── BuiltinFolding.cpp │ ├── BuiltinFolding.h │ ├── Builtins.cpp │ ├── Builtins.h │ ├── BytecodeBuilder.cpp │ ├── Compiler.cpp │ ├── ConstantFolding.cpp │ ├── ConstantFolding.h │ ├── CostModel.cpp │ ├── CostModel.h │ ├── TableShape.cpp │ ├── TableShape.h │ ├── Types.cpp │ ├── Types.h │ ├── ValueTracking.cpp │ ├── ValueTracking.h │ └── lcode.cpp ├── Config ├── include │ └── Luau │ │ ├── Config.h │ │ └── LinterConfig.h └── src │ ├── Config.cpp │ └── LinterConfig.cpp ├── EqSat ├── include │ └── Luau │ │ ├── EGraph.h │ │ ├── Id.h │ │ ├── Language.h │ │ ├── LanguageHash.h │ │ ├── Slice.h │ │ └── UnionFind.h └── src │ ├── Id.cpp │ └── UnionFind.cpp ├── LICENSE.txt ├── Makefile ├── README.md ├── Require ├── Navigator │ ├── include │ │ └── Luau │ │ │ ├── PathUtilities.h │ │ │ └── RequireNavigator.h │ └── src │ │ ├── PathUtilities.cpp │ │ └── RequireNavigator.cpp └── Runtime │ ├── include │ └── Luau │ │ └── Require.h │ └── src │ ├── Navigation.cpp │ ├── Navigation.h │ ├── Require.cpp │ ├── RequireImpl.cpp │ └── RequireImpl.h ├── SECURITY.md ├── Sources.cmake ├── VM ├── include │ ├── lua.h │ ├── luaconf.h │ └── lualib.h └── src │ ├── lapi.cpp │ ├── lapi.h │ ├── laux.cpp │ ├── lbaselib.cpp │ ├── lbitlib.cpp │ ├── lbuffer.cpp │ ├── lbuffer.h │ ├── lbuflib.cpp │ ├── lbuiltins.cpp │ ├── lbuiltins.h │ ├── lbytecode.h │ ├── lcommon.h │ ├── lcorolib.cpp │ ├── ldblib.cpp │ ├── ldebug.cpp │ ├── ldebug.h │ ├── ldo.cpp │ ├── ldo.h │ ├── lfunc.cpp │ ├── lfunc.h │ ├── lgc.cpp │ ├── lgc.h │ ├── lgcdebug.cpp │ ├── linit.cpp │ ├── lmathlib.cpp │ ├── lmem.cpp │ ├── lmem.h │ ├── lnumprint.cpp │ ├── lnumutils.h │ ├── lobject.cpp │ ├── lobject.h │ ├── loslib.cpp │ ├── lperf.cpp │ ├── lstate.cpp │ ├── lstate.h │ ├── lstring.cpp │ ├── lstring.h │ ├── lstrlib.cpp │ ├── ltable.cpp │ ├── ltable.h │ ├── ltablib.cpp │ ├── ltm.cpp │ ├── ltm.h │ ├── ludata.cpp │ ├── ludata.h │ ├── lutf8lib.cpp │ ├── lveclib.cpp │ ├── lvm.h │ ├── lvmexecute.cpp │ ├── lvmload.cpp │ └── lvmutils.cpp ├── bench ├── bench.py ├── bench_support.lua ├── color.py ├── gc │ ├── test_BinaryTree.lua │ ├── test_GC_Boehm_Trees.lua │ ├── test_GC_Tree_Pruning_Eager.lua │ ├── test_GC_Tree_Pruning_Gen.lua │ ├── test_GC_Tree_Pruning_Lazy.lua │ ├── test_GC_hashtable_Keyval.lua │ ├── test_LB_mandel.lua │ ├── test_LargeTableCtor_array.lua │ ├── test_LargeTableCtor_hash.lua │ ├── test_Pcall_pcall_yield.lua │ ├── test_SunSpider_3d-raytrace.lua │ ├── test_TableCreate_nil.lua │ ├── test_TableCreate_number.lua │ ├── test_TableCreate_zerofill.lua │ ├── test_TableMarshal_select.lua │ ├── test_TableMarshal_table_pack.lua │ └── test_TableMarshal_varargs.lua ├── influxbench.py ├── install.bat ├── install.sh ├── measure_time.py ├── micro_tests │ ├── test_AbsSum_abs.lua │ ├── test_AbsSum_and_or.lua │ ├── test_AbsSum_math_abs.lua │ ├── test_Assert.lua │ ├── test_Factorial.lua │ ├── test_Failure_pcall_a_bar.lua │ ├── test_Failure_pcall_game_Foo.lua │ ├── test_Failure_xpcall_a_bar.lua │ ├── test_Failure_xpcall_game_Foo.lua │ ├── test_LargeTableCtor_array.lua │ ├── test_LargeTableCtor_hash.lua │ ├── test_LargeTableSum_loop_index.lua │ ├── test_LargeTableSum_loop_ipairs.lua │ ├── test_LargeTableSum_loop_iter.lua │ ├── test_LargeTableSum_loop_pairs.lua │ ├── test_MethodCalls.lua │ ├── test_OOP_constructor.lua │ ├── test_OOP_method_call.lua │ ├── test_OOP_virtual_constructor.lua │ ├── test_Pcall_call_return.lua │ ├── test_Pcall_pcall_return.lua │ ├── test_Pcall_pcall_yield.lua │ ├── test_Pcall_xpcall_return.lua │ ├── test_SqrtSum_exponent.lua │ ├── test_SqrtSum_math_sqrt.lua │ ├── test_SqrtSum_sqrt.lua │ ├── test_SqrtSum_sqrt_getfenv.lua │ ├── test_SqrtSum_sqrt_roundabout.lua │ ├── test_StringInterp.lua │ ├── test_TableCreate_nil.lua │ ├── test_TableCreate_number.lua │ ├── test_TableCreate_zerofill.lua │ ├── test_TableFind_loop_ipairs.lua │ ├── test_TableFind_table_find.lua │ ├── test_TableInsertion_index_cached.lua │ ├── test_TableInsertion_index_len.lua │ ├── test_TableInsertion_table_insert.lua │ ├── test_TableInsertion_table_insert_index.lua │ ├── test_TableIteration.lua │ ├── test_TableMarshal_select.lua │ ├── test_TableMarshal_table_pack.lua │ ├── test_TableMarshal_table_unpack_array.lua │ ├── test_TableMarshal_table_unpack_range.lua │ ├── test_TableMarshal_varargs.lua │ ├── test_TableMove_empty_table.lua │ ├── test_TableMove_same_table.lua │ ├── test_TableMove_table_create.lua │ ├── test_TableRemoval_table_remove.lua │ ├── test_TableSort.lua │ ├── test_ToNumberString.lua │ ├── test_UpvalueCapture.lua │ ├── test_VariadicSelect.lua │ ├── test_string_lib.lua │ ├── test_table_concat.lua │ └── test_vector_lib.lua ├── other │ ├── LuauPolyfillMap.lua │ ├── boatbomber-HashLib │ │ ├── Base64.lua │ │ ├── HashLib.spec.lua │ │ ├── LICENSE │ │ └── init.lua │ └── regex.lua ├── tabulate.py └── tests │ ├── base64.lua │ ├── chess.lua │ ├── life.lua │ ├── matrixmult.lua │ ├── mesh-normal-scalar.lua │ ├── mesh-normal-vector.lua │ ├── pcmmix.lua │ ├── qsort.lua │ ├── sha256.lua │ ├── shootout │ ├── ack.lua │ ├── binary-trees.lua │ ├── fannkuch-redux.lua │ ├── fixpoint-fact.lua │ ├── heapsort.lua │ ├── mandel.lua │ ├── n-body.lua │ ├── qt.lua │ ├── queen.lua │ ├── scimark.lua │ └── spectral-norm.lua │ ├── sieve.lua │ ├── sunspider │ ├── 3d-cube.lua │ ├── 3d-morph.lua │ ├── 3d-raytrace.lua │ ├── controlflow-recursive.lua │ ├── crypto-aes.lua │ ├── fannkuch.lua │ ├── math-cordic.lua │ ├── math-partial-sums.lua │ └── n-body-oop.lua │ ├── tictactoe.lua │ ├── trig.lua │ ├── vector-math.lua │ └── voxelgen.lua ├── extern ├── .clang-format ├── doctest.h └── isocline │ ├── .gitignore │ ├── LICENSE │ ├── include │ └── isocline.h │ ├── readme.md │ └── src │ ├── attr.c │ ├── attr.h │ ├── bbcode.c │ ├── bbcode.h │ ├── bbcode_colors.c │ ├── common.c │ ├── common.h │ ├── completers.c │ ├── completions.c │ ├── completions.h │ ├── editline.c │ ├── editline_completion.c │ ├── editline_help.c │ ├── editline_history.c │ ├── env.h │ ├── highlight.c │ ├── highlight.h │ ├── history.c │ ├── history.h │ ├── isocline.c │ ├── stringbuf.c │ ├── stringbuf.h │ ├── term.c │ ├── term.h │ ├── term_color.c │ ├── tty.c │ ├── tty.h │ ├── tty_esc.c │ ├── undo.c │ ├── undo.h │ └── wcwidth.c ├── fuzz ├── CMakeLists.txt ├── basic.luau ├── compiler.cpp ├── format.cpp ├── libprotobuf-mutator-patch.patch ├── linter.cpp ├── luau.proto ├── number.cpp ├── parser.cpp ├── proto.cpp ├── protoprint.cpp ├── prototest.cpp ├── syntax.dict ├── transpiler.cpp └── typeck.cpp ├── lua_LICENSE.txt ├── tests ├── AssemblyBuilderA64.test.cpp ├── AssemblyBuilderX64.test.cpp ├── AstJsonEncoder.test.cpp ├── AstQuery.test.cpp ├── AstQueryDsl.cpp ├── AstQueryDsl.h ├── AstVisitor.test.cpp ├── Autocomplete.test.cpp ├── BuiltinDefinitions.test.cpp ├── ClassFixture.cpp ├── ClassFixture.h ├── CodeAllocator.test.cpp ├── Compiler.test.cpp ├── Config.test.cpp ├── Conformance.test.cpp ├── ConformanceIrHooks.h ├── ConstraintGeneratorFixture.cpp ├── ConstraintGeneratorFixture.h ├── ConstraintSolver.test.cpp ├── CostModel.test.cpp ├── DataFlowGraph.test.cpp ├── DenseHash.test.cpp ├── DiffAsserts.cpp ├── DiffAsserts.h ├── Differ.test.cpp ├── EqSat.language.test.cpp ├── EqSat.propositional.test.cpp ├── EqSat.slice.test.cpp ├── EqSatSimplification.test.cpp ├── Error.test.cpp ├── Fixture.cpp ├── Fixture.h ├── FragmentAutocomplete.test.cpp ├── Frontend.test.cpp ├── Generalization.test.cpp ├── InferPolarity.test.cpp ├── InsertionOrderedMap.test.cpp ├── Instantiation2.test.cpp ├── IostreamOptional.h ├── IrBuilder.test.cpp ├── IrCallWrapperX64.test.cpp ├── IrLowering.test.cpp ├── IrRegAllocX64.test.cpp ├── JsonEmitter.test.cpp ├── LValue.test.cpp ├── Lexer.test.cpp ├── Linter.test.cpp ├── Module.test.cpp ├── NonStrictTypeChecker.test.cpp ├── NonstrictMode.test.cpp ├── Normalize.test.cpp ├── NotNull.test.cpp ├── Parser.test.cpp ├── RegisterCallbacks.cpp ├── RegisterCallbacks.h ├── Repl.test.cpp ├── RequireByString.test.cpp ├── RequireTracer.test.cpp ├── RuntimeLimits.test.cpp ├── ScopedFlags.h ├── Set.test.cpp ├── SharedCodeAllocator.test.cpp ├── Simplify.test.cpp ├── StringUtils.test.cpp ├── Subtyping.test.cpp ├── Symbol.test.cpp ├── ToDot.test.cpp ├── ToString.test.cpp ├── TopoSort.test.cpp ├── Transpiler.test.cpp ├── TxnLog.test.cpp ├── TypeFunction.test.cpp ├── TypeFunction.user.test.cpp ├── TypeInfer.aliases.test.cpp ├── TypeInfer.annotations.test.cpp ├── TypeInfer.anyerror.test.cpp ├── TypeInfer.builtins.test.cpp ├── TypeInfer.cfa.test.cpp ├── TypeInfer.classes.test.cpp ├── TypeInfer.definitions.test.cpp ├── TypeInfer.functions.test.cpp ├── TypeInfer.generics.test.cpp ├── TypeInfer.intersectionTypes.test.cpp ├── TypeInfer.loops.test.cpp ├── TypeInfer.modules.test.cpp ├── TypeInfer.negations.test.cpp ├── TypeInfer.oop.test.cpp ├── TypeInfer.operators.test.cpp ├── TypeInfer.primitives.test.cpp ├── TypeInfer.provisional.test.cpp ├── TypeInfer.refinements.test.cpp ├── TypeInfer.singletons.test.cpp ├── TypeInfer.tables.test.cpp ├── TypeInfer.test.cpp ├── TypeInfer.tryUnify.test.cpp ├── TypeInfer.typePacks.test.cpp ├── TypeInfer.typestates.test.cpp ├── TypeInfer.unionTypes.test.cpp ├── TypeInfer.unknownnever.test.cpp ├── TypePack.test.cpp ├── TypePath.test.cpp ├── TypeVar.test.cpp ├── Unifier2.test.cpp ├── Variant.test.cpp ├── VecDeque.test.cpp ├── VisitType.test.cpp ├── conformance │ ├── apicalls.luau │ ├── assert.luau │ ├── attrib.luau │ ├── basic.luau │ ├── bitwise.luau │ ├── buffers.luau │ ├── calls.luau │ ├── clear.luau │ ├── closure.luau │ ├── constructs.luau │ ├── coroutine.luau │ ├── coverage.luau │ ├── cyield.luau │ ├── datetime.luau │ ├── debug.luau │ ├── debugger.luau │ ├── errors.luau │ ├── events.luau │ ├── exceptions.luau │ ├── gc.luau │ ├── ifelseexpr.luau │ ├── interrupt.luau │ ├── iter.luau │ ├── literals.luau │ ├── locals.luau │ ├── math.luau │ ├── move.luau │ ├── native.luau │ ├── native_types.luau │ ├── native_userdata.luau │ ├── ndebug_upvalues.luau │ ├── pcall.luau │ ├── pm.luau │ ├── safeenv.luau │ ├── sort.luau │ ├── strconv.luau │ ├── stringinterp.luau │ ├── strings.luau │ ├── tables.luau │ ├── tmerror.luau │ ├── tpack.luau │ ├── types.luau │ ├── userdata.luau │ ├── utf8.luau │ ├── vararg.luau │ ├── vector.luau │ └── vector_library.luau ├── main.cpp └── require │ ├── with_config │ ├── .luaurc │ └── src │ │ ├── .luaurc │ │ ├── alias_requirer.luau │ │ ├── dependency.luau │ │ ├── directory_alias_requirer.luau │ │ ├── other_dependency.luau │ │ ├── parent_alias_requirer.luau │ │ ├── subdirectory │ │ └── subdirectory_dependency.luau │ │ └── submodule │ │ ├── .luaurc │ │ └── init.luau │ └── without_config │ ├── ambiguous │ ├── directory │ │ ├── dependency.luau │ │ └── dependency │ │ │ └── init.luau │ └── file │ │ ├── dependency.lua │ │ └── dependency.luau │ ├── ambiguous_directory_requirer.luau │ ├── ambiguous_file_requirer.luau │ ├── dependency.luau │ ├── lua │ └── init.lua │ ├── lua_dependency.lua │ ├── luau │ └── init.luau │ ├── module.luau │ ├── nested │ ├── init.luau │ └── submodule.luau │ ├── nested_inits │ ├── init.luau │ └── init │ │ └── init.luau │ ├── nested_inits_requirer.luau │ ├── nested_module_requirer.luau │ ├── proxy_requirer.luau │ └── validate_cache.luau └── tools ├── codegenstat.py ├── codesizeprediction.py ├── faillist.txt ├── flag-bisect.py ├── fuzz ├── fuzzer-postprocess.py ├── fuzzfilter.py ├── requirements.txt └── templates │ └── index.html ├── gdb_printers.py ├── heapgraph.py ├── heapsnapshot.py ├── heapstat.py ├── heuristicstat.py ├── lldb_formatters.lldb ├── lldb_formatters.py ├── natvis ├── Analysis.natvis ├── Ast.natvis ├── CodeGen.natvis ├── Common.natvis └── VM.natvis ├── numprint.py ├── patchtests.py ├── perfgraph.py ├── perfstat.py ├── stack-usage-reporter.py ├── stackdbg.py ├── svg.py ├── test_dcr.py └── tracegraph.py /.clang-format: -------------------------------------------------------------------------------- 1 | BasedOnStyle: LLVM 2 | 3 | AccessModifierOffset: -4 4 | AllowShortBlocksOnASingleLine: Never 5 | AllowShortCaseLabelsOnASingleLine: false 6 | AllowShortFunctionsOnASingleLine: Empty 7 | AllowShortLambdasOnASingleLine: Empty 8 | AllowShortIfStatementsOnASingleLine: Never 9 | AllowShortLoopsOnASingleLine: false 10 | BreakBeforeBraces: Allman 11 | BreakConstructorInitializers: BeforeComma 12 | BreakInheritanceList: BeforeComma 13 | ColumnLimit: 150 14 | IndentCaseLabels: false 15 | SortIncludes: false 16 | IndentWidth: 4 17 | TabWidth: 4 18 | ObjCBlockIndentWidth: 4 19 | UseTab: Never 20 | PointerAlignment: Left 21 | SpaceAfterTemplateKeyword: false 22 | AlignEscapedNewlines: DontAlign 23 | AlwaysBreakTemplateDeclarations: Yes 24 | MaxEmptyLinesToKeep: 10 25 | AllowAllParametersOfDeclarationOnNextLine: false 26 | AlignAfterOpenBracket: BlockIndent 27 | BinPackArguments: false 28 | BinPackParameters: false 29 | PenaltyReturnTypeOnItsOwnLine: 10000 30 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: bug 6 | assignees: '' 7 | 8 | --- 9 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | contact_links: 3 | - name: Questions 4 | url: https://github.com/luau-lang/luau/discussions 5 | about: Please use GitHub Discussions if you have questions or need help. 6 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: enhancement 6 | assignees: '' 7 | 8 | --- 9 | -------------------------------------------------------------------------------- /.github/codecov.yml: -------------------------------------------------------------------------------- 1 | comment: false 2 | coverage: 3 | status: 4 | patch: false 5 | project: 6 | default: 7 | informational: true 8 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /build/ 2 | /build[.-]*/ 3 | /out 4 | /cmake/ 5 | /cmake[.-]*/ 6 | /coverage/ 7 | /.vs/ 8 | /.vscode/ 9 | /fuzz/luau.pb.* 10 | /crash-* 11 | /default.prof* 12 | /fuzz-* 13 | /luau 14 | /luau-tests 15 | /luau-analyze 16 | /luau-bytecode 17 | /luau-compile 18 | __pycache__ 19 | .cache 20 | .clangd 21 | -------------------------------------------------------------------------------- /Analysis/include/Luau/Anyification.h: -------------------------------------------------------------------------------- 1 | // This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | 3 | #pragma once 4 | 5 | #include "Luau/NotNull.h" 6 | #include "Luau/Substitution.h" 7 | #include "Luau/TypeFwd.h" 8 | 9 | #include 10 | 11 | namespace Luau 12 | { 13 | 14 | struct TypeArena; 15 | struct Scope; 16 | struct InternalErrorReporter; 17 | using ScopePtr = std::shared_ptr; 18 | 19 | // A substitution which replaces free types by any 20 | struct Anyification : Substitution 21 | { 22 | Anyification( 23 | TypeArena* arena, 24 | NotNull scope, 25 | NotNull builtinTypes, 26 | InternalErrorReporter* iceHandler, 27 | TypeId anyType, 28 | TypePackId anyTypePack 29 | ); 30 | Anyification( 31 | TypeArena* arena, 32 | const ScopePtr& scope, 33 | NotNull builtinTypes, 34 | InternalErrorReporter* iceHandler, 35 | TypeId anyType, 36 | TypePackId anyTypePack 37 | ); 38 | NotNull scope; 39 | NotNull builtinTypes; 40 | InternalErrorReporter* iceHandler; 41 | 42 | TypeId anyType; 43 | TypePackId anyTypePack; 44 | bool normalizationTooComplex = false; 45 | bool isDirty(TypeId ty) override; 46 | bool isDirty(TypePackId tp) override; 47 | TypeId clean(TypeId ty) override; 48 | TypePackId clean(TypePackId tp) override; 49 | 50 | bool ignoreChildren(TypeId ty) override; 51 | bool ignoreChildren(TypePackId ty) override; 52 | }; 53 | 54 | } // namespace Luau 55 | -------------------------------------------------------------------------------- /Analysis/include/Luau/ApplyTypeFunction.h: -------------------------------------------------------------------------------- 1 | // This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | #pragma once 3 | 4 | #include "Luau/Substitution.h" 5 | #include "Luau/TxnLog.h" 6 | #include "Luau/TypeFwd.h" 7 | 8 | namespace Luau 9 | { 10 | 11 | // A substitution which replaces the type parameters of a type function by arguments 12 | struct ApplyTypeFunction : Substitution 13 | { 14 | ApplyTypeFunction(TypeArena* arena) 15 | : Substitution(TxnLog::empty(), arena) 16 | , encounteredForwardedType(false) 17 | { 18 | } 19 | 20 | // Never set under deferred constraint resolution. 21 | bool encounteredForwardedType; 22 | std::unordered_map typeArguments; 23 | std::unordered_map typePackArguments; 24 | bool ignoreChildren(TypeId ty) override; 25 | bool ignoreChildren(TypePackId tp) override; 26 | bool isDirty(TypeId ty) override; 27 | bool isDirty(TypePackId tp) override; 28 | TypeId clean(TypeId ty) override; 29 | TypePackId clean(TypePackId tp) override; 30 | }; 31 | 32 | } // namespace Luau 33 | -------------------------------------------------------------------------------- /Analysis/include/Luau/AstJsonEncoder.h: -------------------------------------------------------------------------------- 1 | // This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | #pragma once 3 | 4 | #include 5 | #include 6 | 7 | namespace Luau 8 | { 9 | 10 | class AstNode; 11 | struct Comment; 12 | 13 | std::string toJson(AstNode* node); 14 | std::string toJson(AstNode* node, const std::vector& commentLocations); 15 | 16 | } // namespace Luau 17 | -------------------------------------------------------------------------------- /Analysis/include/Luau/Autocomplete.h: -------------------------------------------------------------------------------- 1 | // This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | #pragma once 3 | 4 | #include "Luau/AutocompleteTypes.h" 5 | #include "Luau/Location.h" 6 | #include "Luau/Type.h" 7 | 8 | #include 9 | #include 10 | #include 11 | 12 | namespace Luau 13 | { 14 | 15 | struct Frontend; 16 | struct SourceModule; 17 | struct Module; 18 | struct TypeChecker; 19 | struct FileResolver; 20 | 21 | AutocompleteResult autocomplete(Frontend& frontend, const ModuleName& moduleName, Position position, StringCompletionCallback callback); 22 | 23 | } // namespace Luau 24 | -------------------------------------------------------------------------------- /Analysis/include/Luau/Cancellation.h: -------------------------------------------------------------------------------- 1 | // This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | #pragma once 3 | 4 | #include 5 | 6 | namespace Luau 7 | { 8 | 9 | struct FrontendCancellationToken 10 | { 11 | void cancel() 12 | { 13 | cancelled.store(true); 14 | } 15 | 16 | bool requested() 17 | { 18 | return cancelled.load(); 19 | } 20 | 21 | std::atomic cancelled; 22 | }; 23 | 24 | } // namespace Luau 25 | -------------------------------------------------------------------------------- /Analysis/include/Luau/ConstraintSet.h: -------------------------------------------------------------------------------- 1 | // This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | 3 | #pragma once 4 | 5 | #include "Luau/Constraint.h" 6 | #include "Luau/TypeIds.h" 7 | #include "Luau/Error.h" 8 | 9 | #include 10 | 11 | namespace Luau 12 | { 13 | 14 | struct ConstraintSet 15 | { 16 | NotNull rootScope; 17 | 18 | std::vector constraints; 19 | 20 | // The set of all free types created during constraint generation 21 | TypeIds freeTypes; 22 | 23 | // Map a function's signature scope back to its signature type. Once we've 24 | // dispatched all of the constraints pertaining to a particular free type, 25 | // we use this mapping to generalize that free type. 26 | DenseHashMap scopeToFunction{nullptr}; 27 | 28 | // It is pretty uncommon for constraint generation to itself produce errors, but it can happen. 29 | std::vector errors; 30 | }; 31 | 32 | } // namespace Luau 33 | -------------------------------------------------------------------------------- /Analysis/include/Luau/ControlFlow.h: -------------------------------------------------------------------------------- 1 | // This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | #pragma once 3 | 4 | #include 5 | 6 | namespace Luau 7 | { 8 | 9 | struct Scope; 10 | using ScopePtr = std::shared_ptr; 11 | 12 | enum class ControlFlow 13 | { 14 | None = 0b00001, 15 | Returns = 0b00010, 16 | Throws = 0b00100, 17 | Breaks = 0b01000, 18 | Continues = 0b10000, 19 | }; 20 | 21 | inline ControlFlow operator&(ControlFlow a, ControlFlow b) 22 | { 23 | return ControlFlow(int(a) & int(b)); 24 | } 25 | 26 | inline ControlFlow operator|(ControlFlow a, ControlFlow b) 27 | { 28 | return ControlFlow(int(a) | int(b)); 29 | } 30 | 31 | inline bool matches(ControlFlow a, ControlFlow b) 32 | { 33 | return (a & b) != ControlFlow(0); 34 | } 35 | 36 | } // namespace Luau 37 | -------------------------------------------------------------------------------- /Analysis/include/Luau/EqSatSimplification.h: -------------------------------------------------------------------------------- 1 | // This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | 3 | #pragma once 4 | 5 | #include "Luau/TypeFwd.h" 6 | #include "Luau/NotNull.h" 7 | #include "Luau/DenseHash.h" 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | namespace Luau 14 | { 15 | struct TypeArena; 16 | } 17 | 18 | // The EqSat stuff is pretty template heavy, so we go to some lengths to prevent 19 | // the complexity from leaking outside its implementation sources. 20 | namespace Luau::EqSatSimplification 21 | { 22 | 23 | struct Simplifier; 24 | 25 | using SimplifierPtr = std::unique_ptr; 26 | 27 | SimplifierPtr newSimplifier(NotNull arena, NotNull builtinTypes); 28 | 29 | } // namespace Luau::EqSatSimplification 30 | 31 | namespace Luau 32 | { 33 | 34 | struct EqSatSimplificationResult 35 | { 36 | TypeId result; 37 | 38 | // New type function applications that were created by the reduction phase. 39 | // We return these so that the ConstraintSolver can know to try to reduce 40 | // them. 41 | std::vector newTypeFunctions; 42 | }; 43 | 44 | using EqSatSimplification::newSimplifier; // NOLINT: clang-tidy thinks these are unused. It is incorrect. 45 | using Luau::EqSatSimplification::Simplifier; // NOLINT 46 | using Luau::EqSatSimplification::SimplifierPtr; 47 | 48 | std::optional eqSatSimplify(NotNull simplifier, TypeId ty); 49 | 50 | } // namespace Luau 51 | -------------------------------------------------------------------------------- /Analysis/include/Luau/GlobalTypes.h: -------------------------------------------------------------------------------- 1 | // This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | 3 | #pragma once 4 | 5 | #include "Luau/Module.h" 6 | #include "Luau/NotNull.h" 7 | #include "Luau/Scope.h" 8 | #include "Luau/TypeArena.h" 9 | #include "Luau/TypeFwd.h" 10 | 11 | namespace Luau 12 | { 13 | 14 | struct GlobalTypes 15 | { 16 | explicit GlobalTypes(NotNull builtinTypes); 17 | 18 | NotNull builtinTypes; // Global types are based on builtin types 19 | 20 | TypeArena globalTypes; 21 | SourceModule globalNames; // names for symbols entered into globalScope 22 | 23 | ScopePtr globalScope; // shared by all modules 24 | ScopePtr globalTypeFunctionScope; // shared by all modules 25 | }; 26 | 27 | } // namespace Luau 28 | -------------------------------------------------------------------------------- /Analysis/include/Luau/InferPolarity.h: -------------------------------------------------------------------------------- 1 | // This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | #pragma once 3 | 4 | #include "Luau/NotNull.h" 5 | #include "Luau/TypeFwd.h" 6 | 7 | namespace Luau 8 | { 9 | 10 | struct Scope; 11 | struct TypeArena; 12 | 13 | void inferGenericPolarities(NotNull arena, NotNull scope, TypeId ty); 14 | void inferGenericPolarities(NotNull arena, NotNull scope, TypePackId tp); 15 | 16 | } // namespace Luau 17 | -------------------------------------------------------------------------------- /Analysis/include/Luau/LValue.h: -------------------------------------------------------------------------------- 1 | // This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | #pragma once 3 | 4 | #include "Luau/Variant.h" 5 | #include "Luau/Symbol.h" 6 | #include "Luau/TypeFwd.h" 7 | 8 | #include 9 | #include 10 | 11 | namespace Luau 12 | { 13 | 14 | struct Field; 15 | 16 | // Deprecated. Do not use in new work. 17 | using LValue = Variant; 18 | 19 | struct Field 20 | { 21 | std::shared_ptr parent; 22 | std::string key; 23 | 24 | bool operator==(const Field& rhs) const; 25 | bool operator!=(const Field& rhs) const; 26 | }; 27 | 28 | struct LValueHasher 29 | { 30 | size_t operator()(const LValue& lvalue) const; 31 | }; 32 | 33 | const LValue* baseof(const LValue& lvalue); 34 | 35 | std::optional tryGetLValue(const class AstExpr& expr); 36 | 37 | // Utility function: breaks down an LValue to get at the Symbol 38 | Symbol getBaseSymbol(const LValue& lvalue); 39 | 40 | template 41 | const T* get(const LValue& lvalue) 42 | { 43 | return get_if(&lvalue); 44 | } 45 | 46 | using RefinementMap = std::unordered_map; 47 | 48 | void merge(RefinementMap& l, const RefinementMap& r, std::function f); 49 | void addRefinement(RefinementMap& refis, const LValue& lvalue, TypeId ty); 50 | 51 | } // namespace Luau 52 | -------------------------------------------------------------------------------- /Analysis/include/Luau/Linter.h: -------------------------------------------------------------------------------- 1 | // This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | #pragma once 3 | 4 | #include "Luau/LinterConfig.h" 5 | #include "Luau/Location.h" 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | namespace Luau 12 | { 13 | 14 | struct AstName; 15 | class AstStat; 16 | class AstNameTable; 17 | struct TypeChecker; 18 | struct Module; 19 | 20 | using ScopePtr = std::shared_ptr; 21 | 22 | struct LintResult 23 | { 24 | std::vector errors; 25 | std::vector warnings; 26 | }; 27 | 28 | std::vector lint( 29 | AstStat* root, 30 | const AstNameTable& names, 31 | const ScopePtr& env, 32 | const Module* module, 33 | const std::vector& hotcomments, 34 | const LintOptions& options 35 | ); 36 | 37 | std::vector getDeprecatedGlobals(const AstNameTable& names); 38 | 39 | } // namespace Luau 40 | -------------------------------------------------------------------------------- /Analysis/include/Luau/Metamethods.h: -------------------------------------------------------------------------------- 1 | // This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | #pragma once 3 | 4 | #include "Luau/Ast.h" 5 | 6 | #include 7 | 8 | namespace Luau 9 | { 10 | 11 | inline const std::unordered_map kBinaryOpMetamethods{ 12 | {AstExprBinary::Op::CompareEq, "__eq"}, 13 | {AstExprBinary::Op::CompareNe, "__eq"}, 14 | {AstExprBinary::Op::CompareGe, "__lt"}, 15 | {AstExprBinary::Op::CompareGt, "__le"}, 16 | {AstExprBinary::Op::CompareLe, "__le"}, 17 | {AstExprBinary::Op::CompareLt, "__lt"}, 18 | {AstExprBinary::Op::Add, "__add"}, 19 | {AstExprBinary::Op::Sub, "__sub"}, 20 | {AstExprBinary::Op::Mul, "__mul"}, 21 | {AstExprBinary::Op::Div, "__div"}, 22 | {AstExprBinary::Op::FloorDiv, "__idiv"}, 23 | {AstExprBinary::Op::Pow, "__pow"}, 24 | {AstExprBinary::Op::Mod, "__mod"}, 25 | {AstExprBinary::Op::Concat, "__concat"}, 26 | }; 27 | 28 | inline const std::unordered_map kUnaryOpMetamethods{ 29 | {AstExprUnary::Op::Minus, "__unm"}, 30 | {AstExprUnary::Op::Len, "__len"}, 31 | }; 32 | 33 | } // namespace Luau 34 | -------------------------------------------------------------------------------- /Analysis/include/Luau/NonStrictTypeChecker.h: -------------------------------------------------------------------------------- 1 | // This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | #pragma once 3 | 4 | #include "Luau/DataFlowGraph.h" 5 | #include "Luau/EqSatSimplification.h" 6 | #include "Luau/Module.h" 7 | #include "Luau/NotNull.h" 8 | 9 | namespace Luau 10 | { 11 | 12 | struct BuiltinTypes; 13 | struct TypeFunctionRuntime; 14 | struct UnifierSharedState; 15 | struct TypeCheckLimits; 16 | 17 | void checkNonStrict( 18 | NotNull builtinTypes, 19 | NotNull simplifier, 20 | NotNull typeFunctionRuntime, 21 | NotNull ice, 22 | NotNull unifierState, 23 | NotNull dfg, 24 | NotNull limits, 25 | const SourceModule& sourceModule, 26 | Module* module 27 | ); 28 | 29 | 30 | } // namespace Luau 31 | -------------------------------------------------------------------------------- /Analysis/include/Luau/Polarity.h: -------------------------------------------------------------------------------- 1 | // This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | #pragma once 3 | 4 | #include 5 | 6 | namespace Luau 7 | { 8 | 9 | enum struct Polarity : uint8_t 10 | { 11 | None = 0b000, 12 | Positive = 0b001, 13 | Negative = 0b010, 14 | Mixed = 0b011, 15 | Unknown = 0b100, 16 | }; 17 | 18 | inline Polarity operator|(Polarity lhs, Polarity rhs) 19 | { 20 | return Polarity(uint8_t(lhs) | uint8_t(rhs)); 21 | } 22 | 23 | inline Polarity& operator|=(Polarity& lhs, Polarity rhs) 24 | { 25 | lhs = lhs | rhs; 26 | return lhs; 27 | } 28 | 29 | inline Polarity operator&(Polarity lhs, Polarity rhs) 30 | { 31 | return Polarity(uint8_t(lhs) & uint8_t(rhs)); 32 | } 33 | 34 | inline Polarity& operator&=(Polarity& lhs, Polarity rhs) 35 | { 36 | lhs = lhs & rhs; 37 | return lhs; 38 | } 39 | 40 | inline bool isPositive(Polarity p) 41 | { 42 | return bool(p & Polarity::Positive); 43 | } 44 | 45 | inline bool isNegative(Polarity p) 46 | { 47 | return bool(p & Polarity::Negative); 48 | } 49 | 50 | inline bool isKnown(Polarity p) 51 | { 52 | return p != Polarity::Unknown; 53 | } 54 | 55 | inline Polarity invert(Polarity p) 56 | { 57 | switch (p) 58 | { 59 | case Polarity::Positive: 60 | return Polarity::Negative; 61 | case Polarity::Negative: 62 | return Polarity::Positive; 63 | default: 64 | return p; 65 | } 66 | } 67 | 68 | } // namespace Luau 69 | -------------------------------------------------------------------------------- /Analysis/include/Luau/Quantify.h: -------------------------------------------------------------------------------- 1 | // This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | #pragma once 3 | 4 | #include "Luau/TypeFwd.h" 5 | #include "Luau/DenseHash.h" 6 | #include "Luau/Unifiable.h" 7 | 8 | #include 9 | #include 10 | 11 | namespace Luau 12 | { 13 | 14 | struct TypeArena; 15 | struct Scope; 16 | 17 | void quantify(TypeId ty, TypeLevel level); 18 | 19 | // TODO: This is eerily similar to the pattern that NormalizedExternType 20 | // implements. We could, and perhaps should, merge them together. 21 | template 22 | struct OrderedMap 23 | { 24 | std::vector keys; 25 | DenseHashMap pairings{nullptr}; 26 | 27 | void push(K k, V v) 28 | { 29 | keys.push_back(k); 30 | pairings[k] = v; 31 | } 32 | }; 33 | 34 | } // namespace Luau 35 | -------------------------------------------------------------------------------- /Analysis/include/Luau/RecursionCounter.h: -------------------------------------------------------------------------------- 1 | // This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | #pragma once 3 | 4 | #include "Luau/Common.h" 5 | #include "Luau/Error.h" 6 | 7 | #include 8 | #include 9 | 10 | namespace Luau 11 | { 12 | 13 | struct RecursionLimitException : public InternalCompilerError 14 | { 15 | RecursionLimitException() 16 | : InternalCompilerError("Internal recursion counter limit exceeded") 17 | { 18 | } 19 | }; 20 | 21 | struct RecursionCounter 22 | { 23 | RecursionCounter(int* count) 24 | : count(count) 25 | { 26 | ++(*count); 27 | } 28 | 29 | ~RecursionCounter() 30 | { 31 | LUAU_ASSERT(*count > 0); 32 | --(*count); 33 | } 34 | 35 | protected: 36 | int* count; 37 | }; 38 | 39 | struct RecursionLimiter : RecursionCounter 40 | { 41 | RecursionLimiter(int* count, int limit) 42 | : RecursionCounter(count) 43 | { 44 | if (limit > 0 && *count > limit) 45 | { 46 | throw RecursionLimitException(); 47 | } 48 | } 49 | }; 50 | 51 | } // namespace Luau 52 | -------------------------------------------------------------------------------- /Analysis/include/Luau/RequireTracer.h: -------------------------------------------------------------------------------- 1 | // This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | #pragma once 3 | 4 | #include "Luau/DenseHash.h" 5 | #include "Luau/FileResolver.h" 6 | #include "Luau/Location.h" 7 | 8 | #include 9 | #include 10 | 11 | namespace Luau 12 | { 13 | 14 | class AstNode; 15 | class AstStatBlock; 16 | 17 | struct RequireTraceResult 18 | { 19 | DenseHashMap exprs{nullptr}; 20 | 21 | std::vector> requireList; 22 | }; 23 | 24 | RequireTraceResult traceRequires(FileResolver* fileResolver, AstStatBlock* root, const ModuleName& currentModuleName); 25 | 26 | } // namespace Luau 27 | -------------------------------------------------------------------------------- /Analysis/include/Luau/Simplify.h: -------------------------------------------------------------------------------- 1 | // This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | 3 | #pragma once 4 | 5 | #include "Luau/DenseHash.h" 6 | #include "Luau/NotNull.h" 7 | #include "Luau/TypeFwd.h" 8 | #include 9 | 10 | namespace Luau 11 | { 12 | 13 | struct TypeArena; 14 | 15 | struct SimplifyResult 16 | { 17 | TypeId result; 18 | 19 | DenseHashSet blockedTypes; 20 | }; 21 | 22 | SimplifyResult simplifyIntersection(NotNull builtinTypes, NotNull arena, TypeId left, TypeId right); 23 | SimplifyResult simplifyIntersection(NotNull builtinTypes, NotNull arena, std::set parts); 24 | 25 | SimplifyResult simplifyUnion(NotNull builtinTypes, NotNull arena, TypeId left, TypeId right); 26 | 27 | SimplifyResult simplifyIntersectWithTruthy(NotNull builtinTypes, NotNull arena, TypeId target); 28 | SimplifyResult simplifyIntersectWithFalsy(NotNull builtinTypes, NotNull arena, TypeId target); 29 | 30 | enum class Relation 31 | { 32 | Disjoint, // No A is a B or vice versa 33 | Coincident, // Every A is in B and vice versa 34 | Intersects, // Some As are in B and some Bs are in A. ex (number | string) <-> (string | boolean) 35 | Subset, // Every A is in B 36 | Superset, // Every B is in A 37 | }; 38 | 39 | Relation relate(TypeId left, TypeId right); 40 | 41 | } // namespace Luau 42 | -------------------------------------------------------------------------------- /Analysis/include/Luau/TableLiteralInference.h: -------------------------------------------------------------------------------- 1 | // This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | 3 | #pragma once 4 | 5 | #include "Luau/DenseHash.h" 6 | #include "Luau/NotNull.h" 7 | #include "Luau/TypeFwd.h" 8 | 9 | #include 10 | 11 | namespace Luau 12 | { 13 | 14 | struct TypeArena; 15 | struct BuiltinTypes; 16 | struct Unifier2; 17 | struct Subtyping; 18 | class AstExpr; 19 | 20 | TypeId matchLiteralType( 21 | NotNull> astTypes, 22 | NotNull> astExpectedTypes, 23 | NotNull builtinTypes, 24 | NotNull arena, 25 | NotNull unifier, 26 | NotNull subtyping, 27 | TypeId expectedType, 28 | TypeId exprType, 29 | const AstExpr* expr, 30 | std::vector& toBlock 31 | ); 32 | } // namespace Luau 33 | -------------------------------------------------------------------------------- /Analysis/include/Luau/ToDot.h: -------------------------------------------------------------------------------- 1 | // This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | #pragma once 3 | 4 | #include "Luau/Common.h" 5 | #include "Luau/TypeFwd.h" 6 | 7 | #include 8 | 9 | namespace Luau 10 | { 11 | 12 | struct ToDotOptions 13 | { 14 | bool showPointers = true; // Show pointer value in the node label 15 | bool duplicatePrimitives = true; // Display primitive types and 'any' as separate nodes 16 | }; 17 | 18 | std::string toDot(TypeId ty, const ToDotOptions& opts); 19 | std::string toDot(TypePackId tp, const ToDotOptions& opts); 20 | 21 | std::string toDot(TypeId ty); 22 | std::string toDot(TypePackId tp); 23 | 24 | void dumpDot(TypeId ty); 25 | void dumpDot(TypePackId tp); 26 | 27 | } // namespace Luau 28 | -------------------------------------------------------------------------------- /Analysis/include/Luau/TopoSortStatements.h: -------------------------------------------------------------------------------- 1 | // This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | #pragma once 3 | 4 | #include 5 | 6 | namespace Luau 7 | { 8 | 9 | template 10 | struct AstArray; 11 | 12 | class AstStat; 13 | 14 | bool containsFunctionCall(const AstStat& stat); 15 | bool containsFunctionCallOrReturn(const AstStat& stat); 16 | bool isFunction(const AstStat& stat); 17 | void toposort(std::vector& stats); 18 | 19 | } // namespace Luau 20 | -------------------------------------------------------------------------------- /Analysis/include/Luau/Transpiler.h: -------------------------------------------------------------------------------- 1 | // This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | #pragma once 3 | 4 | #include "Luau/Location.h" 5 | #include "Luau/ParseOptions.h" 6 | 7 | #include 8 | 9 | namespace Luau 10 | { 11 | class AstNode; 12 | class AstStatBlock; 13 | 14 | struct TranspileResult 15 | { 16 | std::string code; 17 | Location errorLocation; 18 | std::string parseError; // Nonempty if the transpile failed 19 | }; 20 | 21 | std::string toString(AstNode* node); 22 | void dump(AstNode* node); 23 | 24 | // Never fails on a well-formed AST 25 | std::string transpile(AstStatBlock& ast); 26 | std::string transpileWithTypes(AstStatBlock& block); 27 | 28 | // Only fails when parsing fails 29 | TranspileResult transpile(std::string_view source, ParseOptions options = ParseOptions{}, bool withTypes = false); 30 | 31 | } // namespace Luau 32 | -------------------------------------------------------------------------------- /Analysis/include/Luau/TypeAttach.h: -------------------------------------------------------------------------------- 1 | // This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | #pragma once 3 | 4 | #include "Luau/Module.h" 5 | 6 | #include 7 | 8 | namespace Luau 9 | { 10 | 11 | struct TypeRehydrationOptions 12 | { 13 | std::unordered_set bannedNames; 14 | bool expandExternTypeProps = false; 15 | }; 16 | 17 | void attachTypeData(SourceModule& source, Module& result); 18 | 19 | AstType* rehydrateAnnotation(TypeId type, Allocator* allocator, const TypeRehydrationOptions& options = {}); 20 | 21 | } // namespace Luau 22 | -------------------------------------------------------------------------------- /Analysis/include/Luau/TypeCheckLimits.h: -------------------------------------------------------------------------------- 1 | // This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | #pragma once 3 | 4 | #include "Luau/Cancellation.h" 5 | #include "Luau/Error.h" 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | namespace Luau 12 | { 13 | 14 | class TimeLimitError : public InternalCompilerError 15 | { 16 | public: 17 | explicit TimeLimitError(const std::string& moduleName) 18 | : InternalCompilerError("Typeinfer failed to complete in allotted time", moduleName) 19 | { 20 | } 21 | }; 22 | 23 | class UserCancelError : public InternalCompilerError 24 | { 25 | public: 26 | explicit UserCancelError(const std::string& moduleName) 27 | : InternalCompilerError("Analysis has been cancelled by user", moduleName) 28 | { 29 | } 30 | }; 31 | 32 | struct TypeCheckLimits 33 | { 34 | std::optional finishTime; 35 | std::optional instantiationChildLimit; 36 | std::optional unifierIterationLimit; 37 | 38 | std::shared_ptr cancellationToken; 39 | }; 40 | 41 | } // namespace Luau 42 | -------------------------------------------------------------------------------- /Analysis/include/Luau/TypeFunctionRuntimeBuilder.h: -------------------------------------------------------------------------------- 1 | // This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | #pragma once 3 | 4 | #include "Luau/Type.h" 5 | #include "Luau/TypeFunction.h" 6 | #include "Luau/TypeFunctionRuntime.h" 7 | 8 | namespace Luau 9 | { 10 | 11 | using Kind = Variant; 12 | 13 | template 14 | const T* get(const Kind& kind) 15 | { 16 | return get_if(&kind); 17 | } 18 | 19 | using TypeFunctionKind = Variant; 20 | 21 | template 22 | const T* get(const TypeFunctionKind& tfkind) 23 | { 24 | return get_if(&tfkind); 25 | } 26 | 27 | struct TypeFunctionRuntimeBuilderState 28 | { 29 | NotNull ctx; 30 | 31 | // List of errors that occur during serialization/deserialization 32 | // At every iteration of serialization/deserialization, if this list.size() != 0, we halt the process 33 | std::vector errors{}; 34 | 35 | TypeFunctionRuntimeBuilderState(NotNull ctx) 36 | : ctx(ctx) 37 | { 38 | } 39 | }; 40 | 41 | TypeFunctionTypeId serialize(TypeId ty, TypeFunctionRuntimeBuilderState* state); 42 | TypeId deserialize(TypeFunctionTypeId ty, TypeFunctionRuntimeBuilderState* state); 43 | 44 | } // namespace Luau 45 | -------------------------------------------------------------------------------- /Analysis/include/Luau/TypeOrPack.h: -------------------------------------------------------------------------------- 1 | // This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | #pragma once 3 | 4 | #include "Luau/Type.h" 5 | #include "Luau/TypePack.h" 6 | #include "Luau/Variant.h" 7 | 8 | #include 9 | 10 | namespace Luau 11 | { 12 | 13 | const void* ptr(TypeOrPack ty); 14 | 15 | template, bool> = true> 16 | const T* get(const TypeOrPack& tyOrTp) 17 | { 18 | return tyOrTp.get_if(); 19 | } 20 | 21 | template, bool> = true> 22 | const T* get(const TypeOrPack& tyOrTp) 23 | { 24 | if (const TypeId* ty = get(tyOrTp)) 25 | return get(*ty); 26 | else 27 | return nullptr; 28 | } 29 | 30 | template, bool> = true> 31 | const T* get(const TypeOrPack& tyOrTp) 32 | { 33 | if (const TypePackId* tp = get(tyOrTp)) 34 | return get(*tp); 35 | else 36 | return nullptr; 37 | } 38 | 39 | TypeOrPack follow(TypeOrPack ty); 40 | 41 | } // namespace Luau 42 | -------------------------------------------------------------------------------- /Analysis/include/Luau/TypePairHash.h: -------------------------------------------------------------------------------- 1 | // This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | #pragma once 3 | 4 | #include "Luau/TypeFwd.h" 5 | 6 | #include 7 | #include 8 | 9 | namespace Luau 10 | { 11 | 12 | struct TypePairHash 13 | { 14 | size_t hashOne(TypeId key) const 15 | { 16 | return (uintptr_t(key) >> 4) ^ (uintptr_t(key) >> 9); 17 | } 18 | 19 | size_t hashOne(TypePackId key) const 20 | { 21 | return (uintptr_t(key) >> 4) ^ (uintptr_t(key) >> 9); 22 | } 23 | 24 | size_t operator()(const std::pair& x) const 25 | { 26 | return hashOne(x.first) ^ (hashOne(x.second) << 1); 27 | } 28 | 29 | size_t operator()(const std::pair& x) const 30 | { 31 | return hashOne(x.first) ^ (hashOne(x.second) << 1); 32 | } 33 | }; 34 | 35 | } // namespace Luau 36 | -------------------------------------------------------------------------------- /Analysis/src/ApplyTypeFunction.cpp: -------------------------------------------------------------------------------- 1 | // This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | 3 | #include "Luau/ApplyTypeFunction.h" 4 | 5 | namespace Luau 6 | { 7 | 8 | bool ApplyTypeFunction::isDirty(TypeId ty) 9 | { 10 | if (typeArguments.count(ty)) 11 | return true; 12 | else if (const FreeType* ftv = get(ty)) 13 | { 14 | if (ftv->forwardedTypeAlias) 15 | encounteredForwardedType = true; 16 | return false; 17 | } 18 | else 19 | return false; 20 | } 21 | 22 | bool ApplyTypeFunction::isDirty(TypePackId tp) 23 | { 24 | if (typePackArguments.count(tp)) 25 | return true; 26 | else 27 | return false; 28 | } 29 | 30 | bool ApplyTypeFunction::ignoreChildren(TypeId ty) 31 | { 32 | if (get(ty)) 33 | return true; 34 | else if (get(ty)) 35 | return true; 36 | else 37 | return false; 38 | } 39 | 40 | bool ApplyTypeFunction::ignoreChildren(TypePackId tp) 41 | { 42 | if (get(tp)) 43 | return true; 44 | else 45 | return false; 46 | } 47 | 48 | TypeId ApplyTypeFunction::clean(TypeId ty) 49 | { 50 | TypeId& arg = typeArguments[ty]; 51 | LUAU_ASSERT(arg); 52 | return arg; 53 | } 54 | 55 | TypePackId ApplyTypeFunction::clean(TypePackId tp) 56 | { 57 | TypePackId& arg = typePackArguments[tp]; 58 | LUAU_ASSERT(arg); 59 | return arg; 60 | } 61 | 62 | } // namespace Luau 63 | -------------------------------------------------------------------------------- /Analysis/src/AutocompleteCore.h: -------------------------------------------------------------------------------- 1 | // This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | #pragma once 3 | 4 | #include "Luau/AutocompleteTypes.h" 5 | 6 | namespace Luau 7 | { 8 | struct Module; 9 | struct FileResolver; 10 | 11 | using ModulePtr = std::shared_ptr; 12 | using ModuleName = std::string; 13 | 14 | 15 | AutocompleteResult autocomplete_( 16 | const ModulePtr& module, 17 | NotNull builtinTypes, 18 | TypeArena* typeArena, 19 | std::vector& ancestry, 20 | Scope* globalScope, 21 | const ScopePtr& scopeAtPosition, 22 | Position position, 23 | FileResolver* fileResolver, 24 | StringCompletionCallback callback 25 | ); 26 | 27 | } // namespace Luau 28 | -------------------------------------------------------------------------------- /Analysis/src/GlobalTypes.cpp: -------------------------------------------------------------------------------- 1 | // This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | 3 | #include "Luau/GlobalTypes.h" 4 | 5 | namespace Luau 6 | { 7 | 8 | GlobalTypes::GlobalTypes(NotNull builtinTypes) 9 | : builtinTypes(builtinTypes) 10 | { 11 | globalScope = std::make_shared(globalTypes.addTypePack(TypePackVar{FreeTypePack{TypeLevel{}}})); 12 | globalTypeFunctionScope = std::make_shared(globalTypes.addTypePack(TypePackVar{FreeTypePack{TypeLevel{}}})); 13 | 14 | globalScope->addBuiltinTypeBinding("any", TypeFun{{}, builtinTypes->anyType}); 15 | globalScope->addBuiltinTypeBinding("nil", TypeFun{{}, builtinTypes->nilType}); 16 | globalScope->addBuiltinTypeBinding("number", TypeFun{{}, builtinTypes->numberType}); 17 | globalScope->addBuiltinTypeBinding("string", TypeFun{{}, builtinTypes->stringType}); 18 | globalScope->addBuiltinTypeBinding("boolean", TypeFun{{}, builtinTypes->booleanType}); 19 | globalScope->addBuiltinTypeBinding("thread", TypeFun{{}, builtinTypes->threadType}); 20 | globalScope->addBuiltinTypeBinding("buffer", TypeFun{{}, builtinTypes->bufferType}); 21 | globalScope->addBuiltinTypeBinding("unknown", TypeFun{{}, builtinTypes->unknownType}); 22 | globalScope->addBuiltinTypeBinding("never", TypeFun{{}, builtinTypes->neverType}); 23 | 24 | unfreeze(*builtinTypes->arena); 25 | TypeId stringMetatableTy = makeStringMetatable(builtinTypes); 26 | asMutable(builtinTypes->stringType)->ty.emplace(PrimitiveType::String, stringMetatableTy); 27 | persist(stringMetatableTy); 28 | freeze(*builtinTypes->arena); 29 | } 30 | 31 | } // namespace Luau 32 | -------------------------------------------------------------------------------- /Analysis/src/Symbol.cpp: -------------------------------------------------------------------------------- 1 | // This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | #include "Luau/Symbol.h" 3 | 4 | #include "Luau/Common.h" 5 | 6 | LUAU_FASTFLAG(LuauSolverV2) 7 | 8 | namespace Luau 9 | { 10 | 11 | bool Symbol::operator==(const Symbol& rhs) const 12 | { 13 | if (local) 14 | return local == rhs.local; 15 | else if (global.value) 16 | return rhs.global.value && global == rhs.global.value; // Subtlety: AstName::operator==(const char*) uses strcmp, not pointer identity. 17 | else 18 | return !rhs.local && !rhs.global.value; // Reflexivity: we already know `this` Symbol is empty, so check that rhs is. 19 | } 20 | 21 | std::string toString(const Symbol& name) 22 | { 23 | if (name.local) 24 | return name.local->name.value; 25 | 26 | LUAU_ASSERT(name.global.value); 27 | return name.global.value; 28 | } 29 | 30 | } // namespace Luau 31 | -------------------------------------------------------------------------------- /Analysis/src/TypeOrPack.cpp: -------------------------------------------------------------------------------- 1 | // This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | 3 | #include "Luau/TypeOrPack.h" 4 | #include "Luau/Common.h" 5 | 6 | namespace Luau 7 | { 8 | 9 | const void* ptr(TypeOrPack tyOrTp) 10 | { 11 | if (auto ty = get(tyOrTp)) 12 | return static_cast(*ty); 13 | else if (auto tp = get(tyOrTp)) 14 | return static_cast(*tp); 15 | else 16 | LUAU_UNREACHABLE(); 17 | } 18 | 19 | TypeOrPack follow(TypeOrPack tyOrTp) 20 | { 21 | if (auto ty = get(tyOrTp)) 22 | return follow(*ty); 23 | else if (auto tp = get(tyOrTp)) 24 | return follow(*tp); 25 | else 26 | LUAU_UNREACHABLE(); 27 | } 28 | 29 | } // namespace Luau 30 | -------------------------------------------------------------------------------- /Analysis/src/Unifiable.cpp: -------------------------------------------------------------------------------- 1 | // This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | #include "Luau/Unifiable.h" 3 | #include "Luau/TypeFwd.h" 4 | #include "Luau/TypePack.h" 5 | 6 | namespace Luau 7 | { 8 | namespace Unifiable 9 | { 10 | 11 | static int nextIndex = 0; 12 | 13 | int freshIndex() 14 | { 15 | return ++nextIndex; 16 | } 17 | 18 | template 19 | Error::Error() 20 | : index(++nextIndex) 21 | { 22 | } 23 | 24 | template 25 | int Error::nextIndex = 0; 26 | 27 | template struct Error; 28 | template struct Error; 29 | 30 | } // namespace Unifiable 31 | } // namespace Luau 32 | -------------------------------------------------------------------------------- /Ast/include/Luau/Allocator.h: -------------------------------------------------------------------------------- 1 | // This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | #pragma once 3 | 4 | #include "Luau/Ast.h" 5 | #include "Luau/Location.h" 6 | #include "Luau/DenseHash.h" 7 | #include "Luau/Common.h" 8 | 9 | #include 10 | 11 | namespace Luau 12 | { 13 | 14 | class Allocator 15 | { 16 | public: 17 | Allocator(); 18 | Allocator(Allocator&&); 19 | 20 | Allocator& operator=(Allocator&&) = delete; 21 | 22 | ~Allocator(); 23 | 24 | void* allocate(size_t size); 25 | 26 | template 27 | T* alloc(Args&&... args) 28 | { 29 | static_assert(std::is_trivially_destructible::value, "Objects allocated with this allocator will never have their destructors run!"); 30 | 31 | T* t = static_cast(allocate(sizeof(T))); 32 | new (t) T(std::forward(args)...); 33 | return t; 34 | } 35 | 36 | private: 37 | struct Page 38 | { 39 | Page* next; 40 | 41 | alignas(8) char data[8192]; 42 | }; 43 | 44 | Page* root; 45 | size_t offset; 46 | }; 47 | 48 | } // namespace Luau 49 | -------------------------------------------------------------------------------- /Ast/include/Luau/Confusables.h: -------------------------------------------------------------------------------- 1 | // This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | #pragma once 3 | 4 | #include 5 | 6 | namespace Luau 7 | { 8 | const char* findConfusable(uint32_t codepoint); 9 | } 10 | -------------------------------------------------------------------------------- /Ast/include/Luau/ParseOptions.h: -------------------------------------------------------------------------------- 1 | // This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | #pragma once 3 | 4 | #include "Luau/Ast.h" 5 | #include "Luau/DenseHash.h" 6 | 7 | #include 8 | 9 | namespace Luau 10 | { 11 | 12 | enum class Mode 13 | { 14 | NoCheck, // Do not perform any inference 15 | Nonstrict, // Unannotated symbols are any 16 | Strict, // Unannotated symbols are inferred 17 | Definition, // Type definition module, has special parsing rules 18 | }; 19 | 20 | struct FragmentParseResumeSettings 21 | { 22 | DenseHashMap localMap{AstName()}; 23 | std::vector localStack; 24 | Position resumePosition; 25 | }; 26 | 27 | struct ParseOptions 28 | { 29 | bool allowDeclarationSyntax = false; 30 | bool captureComments = false; 31 | std::optional parseFragment = std::nullopt; 32 | bool storeCstData = false; 33 | bool noErrorLimit = false; 34 | }; 35 | 36 | } // namespace Luau 37 | -------------------------------------------------------------------------------- /Ast/include/Luau/StringUtils.h: -------------------------------------------------------------------------------- 1 | // This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | #pragma once 3 | 4 | #include "Luau/Common.h" 5 | 6 | #include 7 | #include 8 | 9 | #include 10 | 11 | namespace Luau 12 | { 13 | 14 | std::string format(const char* fmt, ...) LUAU_PRINTF_ATTR(1, 2); 15 | std::string vformat(const char* fmt, va_list args); 16 | 17 | void formatAppend(std::string& str, const char* fmt, ...) LUAU_PRINTF_ATTR(2, 3); 18 | void vformatAppend(std::string& ret, const char* fmt, va_list args); 19 | 20 | std::string join(const std::vector& segments, std::string_view delimiter); 21 | std::string join(const std::vector& segments, std::string_view delimiter); 22 | 23 | std::vector split(std::string_view s, char delimiter); 24 | 25 | // Computes the Damerau-Levenshtein distance of A and B. 26 | // https://en.wikipedia.org/wiki/Damerau-Levenshtein_distance#Distance_with_adjacent_transpositions 27 | size_t editDistance(std::string_view a, std::string_view b); 28 | 29 | bool startsWith(std::string_view lhs, std::string_view rhs); 30 | bool equalsLower(std::string_view lhs, std::string_view rhs); 31 | 32 | size_t hashRange(const char* data, size_t size); 33 | 34 | std::string escape(std::string_view s, bool escapeForInterpString = false); 35 | bool isIdentifier(std::string_view s); 36 | } // namespace Luau 37 | -------------------------------------------------------------------------------- /Ast/src/Allocator.cpp: -------------------------------------------------------------------------------- 1 | // This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | 3 | #include "Luau/Allocator.h" 4 | 5 | namespace Luau 6 | { 7 | 8 | Allocator::Allocator() 9 | : root(static_cast(operator new(sizeof(Page)))) 10 | , offset(0) 11 | { 12 | root->next = nullptr; 13 | } 14 | 15 | Allocator::Allocator(Allocator&& rhs) 16 | : root(rhs.root) 17 | , offset(rhs.offset) 18 | { 19 | rhs.root = nullptr; 20 | rhs.offset = 0; 21 | } 22 | 23 | Allocator::~Allocator() 24 | { 25 | Page* page = root; 26 | 27 | while (page) 28 | { 29 | Page* next = page->next; 30 | 31 | operator delete(page); 32 | 33 | page = next; 34 | } 35 | } 36 | 37 | void* Allocator::allocate(size_t size) 38 | { 39 | constexpr size_t align = alignof(void*) > alignof(double) ? alignof(void*) : alignof(double); 40 | 41 | if (root) 42 | { 43 | uintptr_t data = reinterpret_cast(root->data); 44 | uintptr_t result = (data + offset + align - 1) & ~(align - 1); 45 | if (result + size <= data + sizeof(root->data)) 46 | { 47 | offset = result - data + size; 48 | return reinterpret_cast(result); 49 | } 50 | } 51 | 52 | // allocate new page 53 | size_t pageSize = size > sizeof(root->data) ? size : sizeof(root->data); 54 | void* pageData = operator new(offsetof(Page, data) + pageSize); 55 | 56 | Page* page = static_cast(pageData); 57 | 58 | page->next = root; 59 | 60 | root = page; 61 | offset = size; 62 | 63 | return page->data; 64 | } 65 | 66 | } // namespace Luau 67 | -------------------------------------------------------------------------------- /Ast/src/Location.cpp: -------------------------------------------------------------------------------- 1 | // This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | #include "Luau/Location.h" 3 | 4 | namespace Luau 5 | { 6 | 7 | void Position::shift(const Position& start, const Position& oldEnd, const Position& newEnd) 8 | { 9 | if (*this >= start) 10 | { 11 | if (this->line > oldEnd.line) 12 | this->line += (newEnd.line - oldEnd.line); 13 | else 14 | { 15 | this->line = newEnd.line; 16 | this->column += (newEnd.column - oldEnd.column); 17 | } 18 | } 19 | } 20 | 21 | bool Location::encloses(const Location& l) const 22 | { 23 | return begin <= l.begin && end >= l.end; 24 | } 25 | 26 | bool Location::overlaps(const Location& l) const 27 | { 28 | return (begin <= l.begin && end >= l.begin) || (begin <= l.end && end >= l.end) || (begin >= l.begin && end <= l.end); 29 | } 30 | 31 | bool Location::contains(const Position& p) const 32 | { 33 | return begin <= p && p < end; 34 | } 35 | 36 | bool Location::containsClosed(const Position& p) const 37 | { 38 | return begin <= p && p <= end; 39 | } 40 | 41 | void Location::extend(const Location& other) 42 | { 43 | if (other.begin < begin) 44 | begin = other.begin; 45 | if (other.end > end) 46 | end = other.end; 47 | } 48 | 49 | void Location::shift(const Position& start, const Position& oldEnd, const Position& newEnd) 50 | { 51 | begin.shift(start, oldEnd, newEnd); 52 | end.shift(start, oldEnd, newEnd); 53 | } 54 | 55 | } // namespace Luau 56 | -------------------------------------------------------------------------------- /CLI/include/Luau/AnalyzeRequirer.h: -------------------------------------------------------------------------------- 1 | // This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | #pragma once 3 | 4 | #include "Luau/RequireNavigator.h" 5 | #include "Luau/VfsNavigator.h" 6 | 7 | struct FileNavigationContext : Luau::Require::NavigationContext 8 | { 9 | using NavigateResult = Luau::Require::NavigationContext::NavigateResult; 10 | 11 | FileNavigationContext(std::string requirerPath); 12 | 13 | std::string getRequirerIdentifier() const override; 14 | 15 | // Navigation interface 16 | NavigateResult reset(const std::string& identifier) override; 17 | NavigateResult jumpToAlias(const std::string& path) override; 18 | 19 | NavigateResult toParent() override; 20 | NavigateResult toChild(const std::string& component) override; 21 | 22 | bool isConfigPresent() const override; 23 | virtual ConfigBehavior getConfigBehavior() const override; 24 | virtual std::optional getAlias(const std::string& alias) const override; 25 | virtual std::optional getConfig() const override; 26 | 27 | // Custom capabilities 28 | bool isModulePresent() const; 29 | std::optional getIdentifier() const; 30 | 31 | private: 32 | std::string requirerPath; 33 | VfsNavigator vfs; 34 | }; 35 | -------------------------------------------------------------------------------- /CLI/include/Luau/Coverage.h: -------------------------------------------------------------------------------- 1 | // This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | #pragma once 3 | 4 | struct lua_State; 5 | 6 | void coverageInit(lua_State* L); 7 | bool coverageActive(); 8 | 9 | void coverageTrack(lua_State* L, int funcindex); 10 | void coverageDump(const char* path); 11 | -------------------------------------------------------------------------------- /CLI/include/Luau/FileUtils.h: -------------------------------------------------------------------------------- 1 | // This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | #pragma once 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | std::optional getCurrentWorkingDirectory(); 11 | 12 | std::string normalizePath(std::string_view path); 13 | std::optional resolvePath(std::string_view relativePath, std::string_view baseFilePath); 14 | 15 | std::optional readFile(const std::string& name); 16 | std::optional readStdin(); 17 | 18 | bool hasFileExtension(std::string_view name, const std::vector& extensions); 19 | 20 | bool isAbsolutePath(std::string_view path); 21 | bool isFile(const std::string& path); 22 | bool isDirectory(const std::string& path); 23 | bool traverseDirectory(const std::string& path, const std::function& callback); 24 | 25 | std::vector splitPath(std::string_view path); 26 | std::string joinPaths(std::string_view lhs, std::string_view rhs); 27 | std::optional getParentPath(std::string_view path); 28 | 29 | std::vector getSourceFiles(int argc, char** argv); 30 | -------------------------------------------------------------------------------- /CLI/include/Luau/Flags.h: -------------------------------------------------------------------------------- 1 | // This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | #pragma once 3 | 4 | void setLuauFlagsDefault(); 5 | void setLuauFlags(const char* list); 6 | -------------------------------------------------------------------------------- /CLI/include/Luau/Profiler.h: -------------------------------------------------------------------------------- 1 | // This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | #pragma once 3 | 4 | struct lua_State; 5 | 6 | void profilerStart(lua_State* L, int frequency); 7 | void profilerStop(); 8 | void profilerDump(const char* path); 9 | -------------------------------------------------------------------------------- /CLI/include/Luau/Repl.h: -------------------------------------------------------------------------------- 1 | // This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | #pragma once 3 | 4 | #include "lua.h" 5 | 6 | #include 7 | #include 8 | 9 | using AddCompletionCallback = std::function; 10 | 11 | // Note: These are internal functions which are being exposed in a header 12 | // so they can be included by unit tests. 13 | void* createCliRequireContext(lua_State* L); 14 | void setupState(lua_State* L); 15 | std::string runCode(lua_State* L, const std::string& source); 16 | void getCompletions(lua_State* L, const std::string& editBuffer, const AddCompletionCallback& addCompletionCallback); 17 | 18 | int replMain(int argc, char** argv); 19 | -------------------------------------------------------------------------------- /CLI/include/Luau/ReplRequirer.h: -------------------------------------------------------------------------------- 1 | // This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | #pragma once 3 | 4 | #include "Luau/Require.h" 5 | 6 | #include "Luau/Compiler.h" 7 | #include "Luau/VfsNavigator.h" 8 | 9 | #include "lua.h" 10 | 11 | #include 12 | 13 | void requireConfigInit(luarequire_Configuration* config); 14 | 15 | struct ReplRequirer 16 | { 17 | using CompileOptions = Luau::CompileOptions (*)(); 18 | using BoolCheck = bool (*)(); 19 | using Coverage = void (*)(lua_State*, int); 20 | 21 | ReplRequirer(CompileOptions copts, BoolCheck coverageActive, BoolCheck codegenEnabled, Coverage coverageTrack); 22 | 23 | CompileOptions copts; 24 | BoolCheck coverageActive; 25 | BoolCheck codegenEnabled; 26 | Coverage coverageTrack; 27 | 28 | VfsNavigator vfs; 29 | }; 30 | -------------------------------------------------------------------------------- /CLI/include/Luau/VfsNavigator.h: -------------------------------------------------------------------------------- 1 | // This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | #pragma once 3 | 4 | #include 5 | 6 | enum class NavigationStatus 7 | { 8 | Success, 9 | Ambiguous, 10 | NotFound 11 | }; 12 | 13 | class VfsNavigator 14 | { 15 | public: 16 | NavigationStatus resetToStdIn(); 17 | NavigationStatus resetToPath(const std::string& path); 18 | 19 | NavigationStatus toParent(); 20 | NavigationStatus toChild(const std::string& name); 21 | 22 | std::string getFilePath() const; 23 | std::string getAbsoluteFilePath() const; 24 | std::string getLuaurcPath() const; 25 | 26 | private: 27 | NavigationStatus updateRealPaths(); 28 | 29 | std::string realPath; 30 | std::string absoluteRealPath; 31 | std::string absolutePathPrefix; 32 | 33 | std::string modulePath; 34 | std::string absoluteModulePath; 35 | }; 36 | -------------------------------------------------------------------------------- /CLI/src/ReplEntry.cpp: -------------------------------------------------------------------------------- 1 | // This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | #include "Luau/Repl.h" 3 | #include "Luau/Flags.h" 4 | 5 | int main(int argc, char** argv) 6 | { 7 | setLuauFlagsDefault(); 8 | 9 | return replMain(argc, argv); 10 | } 11 | -------------------------------------------------------------------------------- /CMakePresets.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 6, 3 | "configurePresets": [ 4 | { 5 | "name": "fuzz", 6 | "displayName": "Fuzz", 7 | "description": "Configures required fuzzer settings.", 8 | "binaryDir": "build", 9 | "condition": { 10 | "type": "anyOf", 11 | "conditions": [ 12 | { 13 | "type": "equals", 14 | "lhs": "${hostSystemName}", 15 | "rhs": "Darwin" 16 | }, 17 | { 18 | "type": "equals", 19 | "lhs": "${hostSystemName}", 20 | "rhs": "Linux" 21 | } 22 | ] 23 | }, 24 | "cacheVariables": { 25 | "CMAKE_OSX_ARCHITECTURES": "x86_64", 26 | "CMAKE_BUILD_TYPE": "Release", 27 | "CMAKE_CXX_STANDARD": "17", 28 | "CMAKE_CXX_EXTENSIONS": false 29 | }, 30 | "warnings": { 31 | "dev": false 32 | } 33 | } 34 | ], 35 | "buildPresets": [ 36 | { 37 | "name": "fuzz-proto", 38 | "displayName": "Protobuf Fuzzer", 39 | "description": "Builds the protobuf-based fuzzer and transpiler tools.", 40 | "configurePreset": "fuzz", 41 | "targets": [ 42 | "Luau.Fuzz.Proto", 43 | "Luau.Fuzz.ProtoTest" 44 | ] 45 | } 46 | ] 47 | } 48 | -------------------------------------------------------------------------------- /CodeGen/include/Luau/BytecodeAnalysis.h: -------------------------------------------------------------------------------- 1 | // This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | #pragma once 3 | 4 | #include "Luau/Common.h" 5 | 6 | #include 7 | 8 | #include 9 | 10 | namespace Luau 11 | { 12 | namespace CodeGen 13 | { 14 | 15 | struct IrFunction; 16 | struct HostIrHooks; 17 | 18 | void loadBytecodeTypeInfo(IrFunction& function); 19 | void buildBytecodeBlocks(IrFunction& function, const std::vector& jumpTargets); 20 | void analyzeBytecodeTypes(IrFunction& function, const HostIrHooks& hostHooks); 21 | 22 | } // namespace CodeGen 23 | } // namespace Luau 24 | -------------------------------------------------------------------------------- /CodeGen/include/Luau/CodeBlockUnwind.h: -------------------------------------------------------------------------------- 1 | // This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | #pragma once 3 | 4 | #include 5 | #include 6 | 7 | namespace Luau 8 | { 9 | namespace CodeGen 10 | { 11 | 12 | // context must be an UnwindBuilder 13 | void* createBlockUnwindInfo(void* context, uint8_t* block, size_t blockSize, size_t& startOffset); 14 | void destroyBlockUnwindInfo(void* context, void* unwindData); 15 | 16 | bool isUnwindSupported(); 17 | 18 | } // namespace CodeGen 19 | } // namespace Luau 20 | -------------------------------------------------------------------------------- /CodeGen/include/Luau/CodeGenCommon.h: -------------------------------------------------------------------------------- 1 | // This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | #pragma once 3 | 4 | #include "Luau/Common.h" 5 | 6 | #if defined(LUAU_ASSERTENABLED) 7 | #define CODEGEN_ASSERT(expr) ((void)(!!(expr) || (Luau::assertCallHandler(#expr, __FILE__, __LINE__, __FUNCTION__) && (LUAU_DEBUGBREAK(), 0)))) 8 | #elif defined(CODEGEN_ENABLE_ASSERT_HANDLER) 9 | #define CODEGEN_ASSERT(expr) ((void)(!!(expr) || Luau::assertCallHandler(#expr, __FILE__, __LINE__, __FUNCTION__))) 10 | #else 11 | #define CODEGEN_ASSERT(expr) (void)sizeof(!!(expr)) 12 | #endif 13 | 14 | #if defined(__x86_64__) || defined(_M_X64) 15 | #define CODEGEN_TARGET_X64 16 | #elif defined(__aarch64__) || defined(_M_ARM64) 17 | #define CODEGEN_TARGET_A64 18 | #endif 19 | -------------------------------------------------------------------------------- /CodeGen/include/Luau/Label.h: -------------------------------------------------------------------------------- 1 | // This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | #pragma once 3 | 4 | #include 5 | 6 | namespace Luau 7 | { 8 | namespace CodeGen 9 | { 10 | 11 | struct Label 12 | { 13 | uint32_t id = 0; 14 | uint32_t location = ~0u; 15 | }; 16 | 17 | } // namespace CodeGen 18 | } // namespace Luau 19 | -------------------------------------------------------------------------------- /CodeGen/include/Luau/OptimizeConstProp.h: -------------------------------------------------------------------------------- 1 | // This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | #pragma once 3 | 4 | #include "Luau/IrData.h" 5 | 6 | namespace Luau 7 | { 8 | namespace CodeGen 9 | { 10 | 11 | struct IrBuilder; 12 | 13 | void constPropInBlockChains(IrBuilder& build, bool useValueNumbering); 14 | void createLinearBlocks(IrBuilder& build, bool useValueNumbering); 15 | 16 | } // namespace CodeGen 17 | } // namespace Luau 18 | -------------------------------------------------------------------------------- /CodeGen/include/Luau/OptimizeDeadStore.h: -------------------------------------------------------------------------------- 1 | // This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | #pragma once 3 | 4 | #include "Luau/IrData.h" 5 | 6 | namespace Luau 7 | { 8 | namespace CodeGen 9 | { 10 | 11 | struct IrBuilder; 12 | 13 | void markDeadStoresInBlockChains(IrBuilder& build); 14 | 15 | } // namespace CodeGen 16 | } // namespace Luau 17 | -------------------------------------------------------------------------------- /CodeGen/include/Luau/OptimizeFinalX64.h: -------------------------------------------------------------------------------- 1 | // This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | #pragma once 3 | 4 | #include "Luau/IrData.h" 5 | 6 | namespace Luau 7 | { 8 | namespace CodeGen 9 | { 10 | 11 | void optimizeMemoryOperandsX64(IrFunction& function); 12 | 13 | } // namespace CodeGen 14 | } // namespace Luau 15 | -------------------------------------------------------------------------------- /CodeGen/include/luacodegen.h: -------------------------------------------------------------------------------- 1 | // This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | #pragma once 3 | 4 | // Can be used to reconfigure visibility/exports for public APIs 5 | #ifndef LUACODEGEN_API 6 | #define LUACODEGEN_API extern 7 | #endif 8 | 9 | typedef struct lua_State lua_State; 10 | 11 | // returns 1 if Luau code generator is supported, 0 otherwise 12 | LUACODEGEN_API int luau_codegen_supported(void); 13 | 14 | // create an instance of Luau code generator. you must check that this feature is supported using luau_codegen_supported(). 15 | LUACODEGEN_API void luau_codegen_create(lua_State* L); 16 | 17 | // build target function and all inner functions 18 | LUACODEGEN_API void luau_codegen_compile(lua_State* L, int idx); 19 | -------------------------------------------------------------------------------- /CodeGen/src/BitUtils.h: -------------------------------------------------------------------------------- 1 | // This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | #pragma once 3 | 4 | #include 5 | 6 | #ifdef _MSC_VER 7 | #include 8 | #endif 9 | 10 | namespace Luau 11 | { 12 | namespace CodeGen 13 | { 14 | 15 | inline int countlz(uint32_t n) 16 | { 17 | #ifdef _MSC_VER 18 | unsigned long rl; 19 | return _BitScanReverse(&rl, n) ? 31 - int(rl) : 32; 20 | #else 21 | return n == 0 ? 32 : __builtin_clz(n); 22 | #endif 23 | } 24 | 25 | inline int countrz(uint32_t n) 26 | { 27 | #ifdef _MSC_VER 28 | unsigned long rl; 29 | return _BitScanForward(&rl, n) ? int(rl) : 32; 30 | #else 31 | return n == 0 ? 32 : __builtin_ctz(n); 32 | #endif 33 | } 34 | 35 | inline int lrotate(uint32_t u, int s) 36 | { 37 | // MSVC doesn't recognize the rotate form that is UB-safe 38 | #ifdef _MSC_VER 39 | return _rotl(u, s); 40 | #else 41 | return (u << (s & 31)) | (u >> ((32 - s) & 31)); 42 | #endif 43 | } 44 | 45 | inline int rrotate(uint32_t u, int s) 46 | { 47 | // MSVC doesn't recognize the rotate form that is UB-safe 48 | #ifdef _MSC_VER 49 | return _rotr(u, s); 50 | #else 51 | return (u >> (s & 31)) | (u << ((32 - s) & 31)); 52 | #endif 53 | } 54 | 55 | } // namespace CodeGen 56 | } // namespace Luau 57 | -------------------------------------------------------------------------------- /CodeGen/src/CodeGenA64.h: -------------------------------------------------------------------------------- 1 | // This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | #pragma once 3 | 4 | namespace Luau 5 | { 6 | namespace CodeGen 7 | { 8 | 9 | class BaseCodeGenContext; 10 | struct ModuleHelpers; 11 | 12 | namespace A64 13 | { 14 | 15 | class AssemblyBuilderA64; 16 | 17 | bool initHeaderFunctions(BaseCodeGenContext& codeGenContext); 18 | void assembleHelpers(AssemblyBuilderA64& build, ModuleHelpers& helpers); 19 | 20 | } // namespace A64 21 | } // namespace CodeGen 22 | } // namespace Luau 23 | -------------------------------------------------------------------------------- /CodeGen/src/CodeGenX64.h: -------------------------------------------------------------------------------- 1 | // This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | #pragma once 3 | 4 | namespace Luau 5 | { 6 | namespace CodeGen 7 | { 8 | 9 | class BaseCodeGenContext; 10 | struct ModuleHelpers; 11 | 12 | namespace X64 13 | { 14 | 15 | class AssemblyBuilderX64; 16 | 17 | bool initHeaderFunctions(BaseCodeGenContext& codeGenContext); 18 | void assembleHelpers(AssemblyBuilderX64& build, ModuleHelpers& helpers); 19 | 20 | } // namespace X64 21 | } // namespace CodeGen 22 | } // namespace Luau 23 | -------------------------------------------------------------------------------- /CodeGen/src/EmitBuiltinsX64.h: -------------------------------------------------------------------------------- 1 | // This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | #pragma once 3 | 4 | namespace Luau 5 | { 6 | namespace CodeGen 7 | { 8 | 9 | struct Label; 10 | struct IrOp; 11 | 12 | namespace X64 13 | { 14 | 15 | class AssemblyBuilderX64; 16 | struct OperandX64; 17 | struct IrRegAllocX64; 18 | 19 | void emitBuiltin(IrRegAllocX64& regs, AssemblyBuilderX64& build, int bfid, int ra, int arg, int nresults); 20 | 21 | } // namespace X64 22 | } // namespace CodeGen 23 | } // namespace Luau 24 | -------------------------------------------------------------------------------- /CodeGen/src/EmitCommon.h: -------------------------------------------------------------------------------- 1 | // This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | #pragma once 3 | 4 | #include "Luau/Label.h" 5 | 6 | namespace Luau 7 | { 8 | namespace CodeGen 9 | { 10 | 11 | constexpr unsigned kTValueSizeLog2 = 4; 12 | constexpr unsigned kLuaNodeSizeLog2 = 5; 13 | 14 | // TKey.tt and TKey.next are packed together in a bitfield 15 | constexpr unsigned kOffsetOfTKeyTagNext = 12; // offsetof cannot be used on a bit field 16 | constexpr unsigned kTKeyTagBits = 4; 17 | constexpr unsigned kTKeyTagMask = (1 << kTKeyTagBits) - 1; 18 | 19 | constexpr unsigned kOffsetOfInstructionC = 3; 20 | 21 | // Leaf functions that are placed in every module to perform common instruction sequences 22 | struct ModuleHelpers 23 | { 24 | // A64/X64 25 | Label exitContinueVm; 26 | Label exitNoContinueVm; 27 | Label exitContinueVmClearNativeFlag; 28 | Label updatePcAndContinueInVm; // no reentry 29 | Label return_; 30 | Label interrupt; 31 | 32 | // A64 33 | Label continueCall; // x0: closure 34 | }; 35 | 36 | } // namespace CodeGen 37 | } // namespace Luau 38 | -------------------------------------------------------------------------------- /CodeGen/src/EmitInstructionX64.h: -------------------------------------------------------------------------------- 1 | // This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | #pragma once 3 | 4 | #include 5 | 6 | namespace Luau 7 | { 8 | namespace CodeGen 9 | { 10 | 11 | struct Label; 12 | struct ModuleHelpers; 13 | 14 | namespace X64 15 | { 16 | 17 | class AssemblyBuilderX64; 18 | struct IrRegAllocX64; 19 | 20 | void emitInstCall(AssemblyBuilderX64& build, ModuleHelpers& helpers, int ra, int nparams, int nresults); 21 | void emitInstReturn(AssemblyBuilderX64& build, ModuleHelpers& helpers, int ra, int actualResults, bool functionVariadic); 22 | void emitInstSetList(IrRegAllocX64& regs, AssemblyBuilderX64& build, int ra, int rb, int count, uint32_t index, int knownSize); 23 | void emitInstForGLoop(AssemblyBuilderX64& build, int ra, int aux, Label& loopRepeat); 24 | 25 | } // namespace X64 26 | } // namespace CodeGen 27 | } // namespace Luau 28 | -------------------------------------------------------------------------------- /CodeGen/src/IrTranslateBuiltins.h: -------------------------------------------------------------------------------- 1 | // This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | #pragma once 3 | 4 | namespace Luau 5 | { 6 | namespace CodeGen 7 | { 8 | 9 | struct IrBuilder; 10 | struct IrOp; 11 | 12 | enum class BuiltinImplType 13 | { 14 | None, 15 | UsesFallback, // Uses fallback for unsupported cases 16 | Full, // Is either implemented in full, or exits to VM 17 | }; 18 | 19 | struct BuiltinImplResult 20 | { 21 | BuiltinImplType type; 22 | int actualResultCount; 23 | }; 24 | 25 | BuiltinImplResult translateBuiltin( 26 | IrBuilder& build, 27 | int bfid, 28 | int ra, 29 | int arg, 30 | IrOp args, 31 | IrOp arg3, 32 | int nparams, 33 | int nresults, 34 | IrOp fallback, 35 | int pcpos 36 | ); 37 | 38 | } // namespace CodeGen 39 | } // namespace Luau 40 | -------------------------------------------------------------------------------- /CodeGen/src/IrValueLocationTracking.h: -------------------------------------------------------------------------------- 1 | // This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | #pragma once 3 | 4 | #include "Luau/IrData.h" 5 | 6 | #include 7 | 8 | namespace Luau 9 | { 10 | namespace CodeGen 11 | { 12 | 13 | struct IrValueLocationTracking 14 | { 15 | IrValueLocationTracking(IrFunction& function); 16 | 17 | void setRestoreCallack(void* context, void (*callback)(void* context, IrInst& inst)); 18 | 19 | void beforeInstLowering(IrInst& inst); 20 | void afterInstLowering(IrInst& inst, uint32_t instIdx); 21 | 22 | void recordRestoreOp(uint32_t instIdx, IrOp location); 23 | void invalidateRestoreOp(IrOp location, bool skipValueInvalidation); 24 | void invalidateRestoreVmRegs(int start, int count); 25 | 26 | IrFunction& function; 27 | 28 | std::array vmRegValue; 29 | 30 | // For range/full invalidations, we only want to visit a limited number of data that we have recorded 31 | int maxReg = 0; 32 | 33 | void* restoreCallbackCtx = nullptr; 34 | void (*restoreCallback)(void* context, IrInst& inst) = nullptr; 35 | }; 36 | 37 | } // namespace CodeGen 38 | } // namespace Luau 39 | -------------------------------------------------------------------------------- /CodeGen/src/lcodegen.cpp: -------------------------------------------------------------------------------- 1 | // This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | #include "luacodegen.h" 3 | 4 | #include "Luau/CodeGen.h" 5 | 6 | #include "lapi.h" 7 | 8 | int luau_codegen_supported() 9 | { 10 | return Luau::CodeGen::isSupported(); 11 | } 12 | 13 | void luau_codegen_create(lua_State* L) 14 | { 15 | Luau::CodeGen::create(L); 16 | } 17 | 18 | void luau_codegen_compile(lua_State* L, int idx) 19 | { 20 | Luau::CodeGen::CompilationOptions options; 21 | Luau::CodeGen::compile(L, idx, options); 22 | } 23 | -------------------------------------------------------------------------------- /Common/include/Luau/BytecodeUtils.h: -------------------------------------------------------------------------------- 1 | // This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | #pragma once 3 | 4 | #include "Luau/Bytecode.h" 5 | 6 | namespace Luau 7 | { 8 | 9 | inline int getOpLength(LuauOpcode op) 10 | { 11 | switch (op) 12 | { 13 | case LOP_GETGLOBAL: 14 | case LOP_SETGLOBAL: 15 | case LOP_GETIMPORT: 16 | case LOP_GETTABLEKS: 17 | case LOP_SETTABLEKS: 18 | case LOP_NAMECALL: 19 | case LOP_JUMPIFEQ: 20 | case LOP_JUMPIFLE: 21 | case LOP_JUMPIFLT: 22 | case LOP_JUMPIFNOTEQ: 23 | case LOP_JUMPIFNOTLE: 24 | case LOP_JUMPIFNOTLT: 25 | case LOP_NEWTABLE: 26 | case LOP_SETLIST: 27 | case LOP_FORGLOOP: 28 | case LOP_LOADKX: 29 | case LOP_FASTCALL2: 30 | case LOP_FASTCALL2K: 31 | case LOP_FASTCALL3: 32 | case LOP_JUMPXEQKNIL: 33 | case LOP_JUMPXEQKB: 34 | case LOP_JUMPXEQKN: 35 | case LOP_JUMPXEQKS: 36 | return 2; 37 | 38 | default: 39 | return 1; 40 | } 41 | } 42 | 43 | } // namespace Luau 44 | -------------------------------------------------------------------------------- /Common/include/Luau/ExperimentalFlags.h: -------------------------------------------------------------------------------- 1 | // This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | #pragma once 3 | 4 | #include 5 | 6 | namespace Luau 7 | { 8 | 9 | inline bool isAnalysisFlagExperimental(const char* flag) 10 | { 11 | // Flags in this list are disabled by default in various command-line tools. They may have behavior that is not fully final, 12 | // or critical bugs that are found after the code has been submitted. This list is intended _only_ for flags that affect 13 | // Luau's type checking. Flags that may change runtime behavior (e.g.: parser or VM flags) are not appropriate for this list. 14 | static const char* const kList[] = { 15 | "LuauInstantiateInSubtyping", // requires some fixes to lua-apps code 16 | "LuauFixIndexerSubtypingOrdering", // requires some small fixes to lua-apps code since this fixes a false negative 17 | "StudioReportLuauAny2", // takes telemetry data for usage of any types 18 | "LuauTableCloneClonesType3", // requires fixes in lua-apps code, terrifyingly 19 | "LuauSolverV2", 20 | // makes sure we always have at least one entry 21 | nullptr, 22 | }; 23 | 24 | for (const char* item : kList) 25 | if (item && strcmp(item, flag) == 0) 26 | return true; 27 | 28 | return false; 29 | } 30 | 31 | } // namespace Luau 32 | -------------------------------------------------------------------------------- /Compiler/src/BuiltinFolding.h: -------------------------------------------------------------------------------- 1 | // This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | #pragma once 3 | 4 | #include "ConstantFolding.h" 5 | 6 | namespace Luau 7 | { 8 | namespace Compile 9 | { 10 | 11 | Constant foldBuiltin(int bfid, const Constant* args, size_t count); 12 | Constant foldBuiltinMath(AstName index); 13 | 14 | } // namespace Compile 15 | } // namespace Luau 16 | -------------------------------------------------------------------------------- /Compiler/src/ConstantFolding.h: -------------------------------------------------------------------------------- 1 | // This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | #pragma once 3 | 4 | #include "Luau/Compiler.h" 5 | 6 | #include "ValueTracking.h" 7 | 8 | namespace Luau 9 | { 10 | namespace Compile 11 | { 12 | 13 | struct Constant 14 | { 15 | enum Type 16 | { 17 | Type_Unknown, 18 | Type_Nil, 19 | Type_Boolean, 20 | Type_Number, 21 | Type_Vector, 22 | Type_String, 23 | }; 24 | 25 | Type type = Type_Unknown; 26 | unsigned int stringLength = 0; 27 | 28 | union 29 | { 30 | bool valueBoolean; 31 | double valueNumber; 32 | float valueVector[4]; 33 | const char* valueString = nullptr; // length stored in stringLength 34 | }; 35 | 36 | bool isTruthful() const 37 | { 38 | LUAU_ASSERT(type != Type_Unknown); 39 | return type != Type_Nil && !(type == Type_Boolean && valueBoolean == false); 40 | } 41 | 42 | AstArray getString() const 43 | { 44 | LUAU_ASSERT(type == Type_String); 45 | return {valueString, stringLength}; 46 | } 47 | }; 48 | 49 | void foldConstants( 50 | DenseHashMap& constants, 51 | DenseHashMap& variables, 52 | DenseHashMap& locals, 53 | const DenseHashMap* builtins, 54 | bool foldLibraryK, 55 | LibraryMemberConstantCallback libraryMemberConstantCb, 56 | AstNode* root 57 | ); 58 | 59 | } // namespace Compile 60 | } // namespace Luau 61 | -------------------------------------------------------------------------------- /Compiler/src/CostModel.h: -------------------------------------------------------------------------------- 1 | // This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | #pragma once 3 | 4 | #include "Luau/Ast.h" 5 | #include "Luau/DenseHash.h" 6 | 7 | namespace Luau 8 | { 9 | namespace Compile 10 | { 11 | 12 | // cost model: 8 bytes, where first byte is the baseline cost, and the next 7 bytes are discounts for when variable #i is constant 13 | uint64_t modelCost(AstNode* root, AstLocal* const* vars, size_t varCount, const DenseHashMap& builtins); 14 | 15 | // cost is computed as B - sum(Di * Ci), where B is baseline cost, Di is the discount for each variable and Ci is 1 when variable #i is constant 16 | int computeCost(uint64_t model, const bool* varsConst, size_t varCount); 17 | 18 | // get loop trip count or -1 if we can't compute it precisely 19 | int getTripCount(double from, double to, double step); 20 | 21 | } // namespace Compile 22 | } // namespace Luau 23 | -------------------------------------------------------------------------------- /Compiler/src/TableShape.h: -------------------------------------------------------------------------------- 1 | // This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | #pragma once 3 | 4 | #include "Luau/Ast.h" 5 | #include "Luau/DenseHash.h" 6 | 7 | namespace Luau 8 | { 9 | namespace Compile 10 | { 11 | 12 | struct TableShape 13 | { 14 | unsigned int arraySize = 0; 15 | unsigned int hashSize = 0; 16 | }; 17 | 18 | void predictTableShapes(DenseHashMap& shapes, AstNode* root); 19 | 20 | } // namespace Compile 21 | } // namespace Luau 22 | -------------------------------------------------------------------------------- /Compiler/src/ValueTracking.h: -------------------------------------------------------------------------------- 1 | // This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | #pragma once 3 | 4 | #include "Luau/Ast.h" 5 | #include "Luau/DenseHash.h" 6 | 7 | namespace Luau 8 | { 9 | class AstNameTable; 10 | } 11 | 12 | namespace Luau 13 | { 14 | namespace Compile 15 | { 16 | 17 | enum class Global 18 | { 19 | Default = 0, 20 | Mutable, // builtin that has contents unknown at compile time, blocks GETIMPORT for chains 21 | Written, // written in the code which means we can't reason about the value 22 | }; 23 | 24 | struct Variable 25 | { 26 | AstExpr* init = nullptr; // initial value of the variable; filled by trackValues 27 | bool written = false; // is the variable ever assigned to? filled by trackValues 28 | bool constant = false; // is the variable's value a compile-time constant? filled by constantFold 29 | }; 30 | 31 | void assignMutable(DenseHashMap& globals, const AstNameTable& names, const char* const* mutableGlobals); 32 | void trackValues(DenseHashMap& globals, DenseHashMap& variables, AstNode* root); 33 | 34 | inline Global getGlobalState(const DenseHashMap& globals, AstName name) 35 | { 36 | const Global* it = globals.find(name); 37 | 38 | return it ? *it : Global::Default; 39 | } 40 | 41 | } // namespace Compile 42 | } // namespace Luau 43 | -------------------------------------------------------------------------------- /EqSat/include/Luau/Id.h: -------------------------------------------------------------------------------- 1 | // This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | #pragma once 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | namespace Luau::EqSat 9 | { 10 | 11 | struct Id final 12 | { 13 | explicit Id(uint32_t id); 14 | 15 | explicit operator uint32_t() const; 16 | 17 | bool operator==(Id rhs) const; 18 | bool operator!=(Id rhs) const; 19 | 20 | bool operator<(Id rhs) const; 21 | 22 | private: 23 | uint32_t id; 24 | }; 25 | 26 | } // namespace Luau::EqSat 27 | 28 | template<> 29 | struct std::hash 30 | { 31 | size_t operator()(Luau::EqSat::Id id) const; 32 | }; 33 | -------------------------------------------------------------------------------- /EqSat/include/Luau/LanguageHash.h: -------------------------------------------------------------------------------- 1 | // This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | #pragma once 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | namespace Luau::EqSat 10 | { 11 | 12 | template 13 | struct LanguageHash 14 | { 15 | size_t operator()(const T& t, decltype(std::hash{}(std::declval()))* = 0) const 16 | { 17 | return std::hash{}(t); 18 | } 19 | }; 20 | 21 | template 22 | size_t languageHash(const T& lang) 23 | { 24 | return LanguageHash{}(lang); 25 | } 26 | 27 | inline void hashCombine(size_t& seed, size_t hash) 28 | { 29 | // Golden Ratio constant used for better hash scattering 30 | // See https://softwareengineering.stackexchange.com/a/402543 31 | seed ^= hash + 0x9e3779b9 + (seed << 6) + (seed >> 2); 32 | } 33 | 34 | template 35 | struct LanguageHash> 36 | { 37 | size_t operator()(const std::array& array) const 38 | { 39 | size_t seed = 0; 40 | for (const T& t : array) 41 | hashCombine(seed, languageHash(t)); 42 | return seed; 43 | } 44 | }; 45 | 46 | template 47 | struct LanguageHash> 48 | { 49 | size_t operator()(const std::vector& vector) const 50 | { 51 | size_t seed = 0; 52 | for (const T& t : vector) 53 | hashCombine(seed, languageHash(t)); 54 | return seed; 55 | } 56 | }; 57 | 58 | } // namespace Luau::EqSat 59 | -------------------------------------------------------------------------------- /EqSat/include/Luau/UnionFind.h: -------------------------------------------------------------------------------- 1 | // This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | #pragma once 3 | 4 | #include "Luau/Id.h" 5 | 6 | #include 7 | 8 | namespace Luau::EqSat 9 | { 10 | 11 | /// See . 12 | struct UnionFind final 13 | { 14 | Id makeSet(); 15 | Id find(Id id) const; 16 | Id find(Id id); 17 | 18 | // Merge aSet with bSet and return the canonicalized Id into the merged set. 19 | Id merge(Id aSet, Id bSet); 20 | 21 | private: 22 | std::vector parents; 23 | std::vector ranks; 24 | 25 | private: 26 | Id canonicalize(Id id) const; 27 | }; 28 | 29 | } // namespace Luau::EqSat 30 | -------------------------------------------------------------------------------- /EqSat/src/Id.cpp: -------------------------------------------------------------------------------- 1 | // This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | #include "Luau/Id.h" 3 | #include "Luau/Common.h" 4 | 5 | namespace Luau::EqSat 6 | { 7 | 8 | Id::Id(uint32_t id) 9 | : id(id) 10 | { 11 | } 12 | 13 | Id::operator uint32_t() const 14 | { 15 | return id; 16 | } 17 | 18 | bool Id::operator==(Id rhs) const 19 | { 20 | return id == rhs.id; 21 | } 22 | 23 | bool Id::operator!=(Id rhs) const 24 | { 25 | return id != rhs.id; 26 | } 27 | 28 | bool Id::operator<(Id rhs) const 29 | { 30 | return id < rhs.id; 31 | } 32 | 33 | } // namespace Luau::EqSat 34 | 35 | size_t std::hash::operator()(Luau::EqSat::Id id) const 36 | { 37 | return std::hash()(uint32_t(id)); 38 | } 39 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019-2025 Roblox Corporation 4 | Copyright (c) 1994–2019 Lua.org, PUC-Rio. 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy of 7 | this software and associated documentation files (the "Software"), to deal in 8 | the Software without restriction, including without limitation the rights to 9 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 10 | of the Software, and to permit persons to whom the Software is furnished to do 11 | so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | -------------------------------------------------------------------------------- /Require/Navigator/include/Luau/PathUtilities.h: -------------------------------------------------------------------------------- 1 | // This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | #pragma once 3 | 4 | #include 5 | #include 6 | 7 | namespace Luau::Require 8 | { 9 | 10 | enum class PathType 11 | { 12 | RelativeToCurrent, 13 | RelativeToParent, 14 | Aliased, 15 | Unsupported 16 | }; 17 | 18 | PathType getPathType(std::string_view path); 19 | 20 | std::pair splitPath(std::string_view path); 21 | 22 | } // namespace Luau::Require 23 | -------------------------------------------------------------------------------- /Require/Navigator/src/PathUtilities.cpp: -------------------------------------------------------------------------------- 1 | // This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | 3 | #include "Luau/PathUtilities.h" 4 | 5 | #include 6 | 7 | namespace Luau::Require 8 | { 9 | 10 | PathType getPathType(std::string_view path) 11 | { 12 | if (path.size() >= 2 && path.substr(0, 2) == "./") 13 | return PathType::RelativeToCurrent; 14 | if (path.size() >= 3 && path.substr(0, 3) == "../") 15 | return PathType::RelativeToParent; 16 | if (path.size() >= 1 && path[0] == '@') 17 | return PathType::Aliased; 18 | 19 | return PathType::Unsupported; 20 | } 21 | 22 | std::pair splitPath(std::string_view path) 23 | { 24 | size_t pos = path.find_first_of('/'); 25 | if (pos == std::string_view::npos) 26 | return {path, {}}; 27 | 28 | return {path.substr(0, pos), path.substr(pos + 1)}; 29 | } 30 | 31 | } // namespace Luau::Require 32 | -------------------------------------------------------------------------------- /Require/Runtime/src/RequireImpl.h: -------------------------------------------------------------------------------- 1 | // This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | #pragma once 3 | 4 | struct lua_State; 5 | 6 | namespace Luau::Require 7 | { 8 | 9 | int lua_require(lua_State* L); 10 | int lua_proxyrequire(lua_State* L); 11 | int lua_requirecont(lua_State* L, int status); 12 | 13 | int registerModuleImpl(lua_State* L); 14 | 15 | int clearCacheEntry(lua_State* L); 16 | int clearCache(lua_State* L); 17 | 18 | } // namespace Luau::Require 19 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Guarantees 2 | 3 | Luau provides a safe sandbox that scripts can not escape from, short of vulnerabilities in custom C functions exposed by the host. This includes the virtual machine, builtin libraries and native code generation facilities. 4 | 5 | Any source code can not result in memory safety errors or crashes during its compilation or execution. Violations of memory safety are considered vulnerabilities. 6 | 7 | Note that Luau does not provide termination guarantees - some code may exhaust CPU or RAM resources on the system during compilation or execution. 8 | 9 | The runtime expects valid bytecode as an input. Feeding bytecode that was not produced by Luau compiler into the VM is not supported, and 10 | doesn't come with any security guarantees; make sure to sign and/or encrypt the bytecode when it crosses a network or file system boundary to avoid tampering. 11 | 12 | # Reporting a Vulnerability 13 | 14 | You can report security bugs via [HackerOne](https://hackerone.com/roblox). Please refer to the linked page for rules of the bounty program. 15 | -------------------------------------------------------------------------------- /VM/src/lapi.h: -------------------------------------------------------------------------------- 1 | // This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | // This code is based on Lua 5.x implementation licensed under MIT License; see lua_LICENSE.txt for details 3 | #pragma once 4 | 5 | #include "lobject.h" 6 | 7 | LUAI_FUNC const TValue* luaA_toobject(lua_State* L, int idx); 8 | LUAI_FUNC void luaA_pushobject(lua_State* L, const TValue* o); 9 | -------------------------------------------------------------------------------- /VM/src/lbuffer.cpp: -------------------------------------------------------------------------------- 1 | // This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | #include "lbuffer.h" 3 | 4 | #include "lgc.h" 5 | #include "lmem.h" 6 | 7 | #include 8 | 9 | Buffer* luaB_newbuffer(lua_State* L, size_t s) 10 | { 11 | if (s > MAX_BUFFER_SIZE) 12 | luaM_toobig(L); 13 | 14 | Buffer* b = luaM_newgco(L, Buffer, sizebuffer(s), L->activememcat); 15 | luaC_init(L, b, LUA_TBUFFER); 16 | b->len = unsigned(s); 17 | memset(b->data, 0, b->len); 18 | return b; 19 | } 20 | 21 | void luaB_freebuffer(lua_State* L, Buffer* b, lua_Page* page) 22 | { 23 | luaM_freegco(L, b, sizebuffer(b->len), b->memcat, page); 24 | } 25 | -------------------------------------------------------------------------------- /VM/src/lbuffer.h: -------------------------------------------------------------------------------- 1 | // This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | #pragma once 3 | 4 | #include "lobject.h" 5 | 6 | // buffer size limit 7 | #define MAX_BUFFER_SIZE (1 << 30) 8 | 9 | // GCObject size has to be at least 16 bytes, so a minimum of 8 bytes is always reserved 10 | #define sizebuffer(len) (offsetof(Buffer, data) + ((len) < 8 ? 8 : (len))) 11 | 12 | LUAI_FUNC Buffer* luaB_newbuffer(lua_State* L, size_t s); 13 | LUAI_FUNC void luaB_freebuffer(lua_State* L, Buffer* u, struct lua_Page* page); 14 | -------------------------------------------------------------------------------- /VM/src/lbuiltins.h: -------------------------------------------------------------------------------- 1 | // This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | // This code is based on Lua 5.x implementation licensed under MIT License; see lua_LICENSE.txt for details 3 | #pragma once 4 | 5 | #include "lobject.h" 6 | 7 | typedef int (*luau_FastFunction)(lua_State* L, StkId res, TValue* arg0, int nresults, StkId args, int nparams); 8 | 9 | extern const luau_FastFunction luauF_table[256]; 10 | -------------------------------------------------------------------------------- /VM/src/lbytecode.h: -------------------------------------------------------------------------------- 1 | // This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | // This code is based on Lua 5.x implementation licensed under MIT License; see lua_LICENSE.txt for details 3 | #pragma once 4 | 5 | // This is a forwarding header for Luau bytecode definition 6 | #include "Luau/Bytecode.h" 7 | -------------------------------------------------------------------------------- /VM/src/lcommon.h: -------------------------------------------------------------------------------- 1 | // This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | // This code is based on Lua 5.x implementation licensed under MIT License; see lua_LICENSE.txt for details 3 | #pragma once 4 | 5 | #include 6 | #include 7 | 8 | #include "luaconf.h" 9 | 10 | #include "Luau/Common.h" 11 | 12 | // internal assertions for in-house debugging 13 | #define check_exp(c, e) (LUAU_ASSERT(c), (e)) 14 | #define api_check(l, e) LUAU_ASSERT(e) 15 | 16 | #ifndef cast_to 17 | #define cast_to(t, exp) ((t)(exp)) 18 | #endif 19 | 20 | #define cast_byte(i) cast_to(uint8_t, (i)) 21 | #define cast_num(i) cast_to(double, (i)) 22 | #define cast_int(i) cast_to(int, (i)) 23 | 24 | /* 25 | ** type for virtual-machine instructions 26 | ** must be an unsigned with (at least) 4 bytes (see details in lopcodes.h) 27 | */ 28 | typedef uint32_t Instruction; 29 | 30 | /* 31 | ** macro to control inclusion of some hard tests on stack reallocation 32 | */ 33 | #if defined(HARDSTACKTESTS) && HARDSTACKTESTS 34 | #define condhardstacktests(x) (x) 35 | #else 36 | #define condhardstacktests(x) ((void)0) 37 | #endif 38 | 39 | /* 40 | ** macro to control inclusion of some hard tests on garbage collection 41 | */ 42 | #if defined(HARDMEMTESTS) && HARDMEMTESTS 43 | #define condhardmemtests(x, l) (HARDMEMTESTS >= l ? (x) : (void)0) 44 | #else 45 | #define condhardmemtests(x, l) ((void)0) 46 | #endif 47 | -------------------------------------------------------------------------------- /VM/src/lfunc.h: -------------------------------------------------------------------------------- 1 | // This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | // This code is based on Lua 5.x implementation licensed under MIT License; see lua_LICENSE.txt for details 3 | #pragma once 4 | 5 | #include "lobject.h" 6 | 7 | #define sizeCclosure(n) (offsetof(Closure, c.upvals) + sizeof(TValue) * (n)) 8 | #define sizeLclosure(n) (offsetof(Closure, l.uprefs) + sizeof(TValue) * (n)) 9 | 10 | LUAI_FUNC Proto* luaF_newproto(lua_State* L); 11 | LUAI_FUNC Closure* luaF_newLclosure(lua_State* L, int nelems, LuaTable* e, Proto* p); 12 | LUAI_FUNC Closure* luaF_newCclosure(lua_State* L, int nelems, LuaTable* e); 13 | LUAI_FUNC UpVal* luaF_findupval(lua_State* L, StkId level); 14 | LUAI_FUNC void luaF_close(lua_State* L, StkId level); 15 | LUAI_FUNC void luaF_closeupval(lua_State* L, UpVal* uv, bool dead); 16 | LUAI_FUNC void luaF_freeproto(lua_State* L, Proto* f, struct lua_Page* page); 17 | LUAI_FUNC void luaF_freeclosure(lua_State* L, Closure* c, struct lua_Page* page); 18 | LUAI_FUNC void luaF_freeupval(lua_State* L, UpVal* uv, struct lua_Page* page); 19 | LUAI_FUNC const LocVar* luaF_getlocal(const Proto* func, int local_number, int pc); 20 | LUAI_FUNC const LocVar* luaF_findlocal(const Proto* func, int local_reg, int pc); 21 | -------------------------------------------------------------------------------- /VM/src/lstring.h: -------------------------------------------------------------------------------- 1 | // This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | // This code is based on Lua 5.x implementation licensed under MIT License; see lua_LICENSE.txt for details 3 | #pragma once 4 | 5 | #include "lobject.h" 6 | #include "lstate.h" 7 | 8 | // string size limit 9 | #define MAXSSIZE (1 << 30) 10 | 11 | // string atoms are not defined by default; the storage is 16-bit integer 12 | #define ATOM_UNDEF -32768 13 | 14 | #define sizestring(len) (offsetof(TString, data) + len + 1) 15 | 16 | #define luaS_new(L, s) (luaS_newlstr(L, s, strlen(s))) 17 | #define luaS_newliteral(L, s) (luaS_newlstr(L, "" s, (sizeof(s) / sizeof(char)) - 1)) 18 | 19 | #define luaS_fix(s) l_setbit((s)->marked, FIXEDBIT) 20 | 21 | LUAI_FUNC unsigned int luaS_hash(const char* str, size_t len); 22 | 23 | LUAI_FUNC void luaS_resize(lua_State* L, int newsize); 24 | 25 | LUAI_FUNC TString* luaS_newlstr(lua_State* L, const char* str, size_t l); 26 | LUAI_FUNC void luaS_free(lua_State* L, TString* ts, struct lua_Page* page); 27 | 28 | LUAI_FUNC TString* luaS_bufstart(lua_State* L, size_t size); 29 | LUAI_FUNC TString* luaS_buffinish(lua_State* L, TString* ts); 30 | -------------------------------------------------------------------------------- /VM/src/ludata.cpp: -------------------------------------------------------------------------------- 1 | // This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | // This code is based on Lua 5.x implementation licensed under MIT License; see lua_LICENSE.txt for details 3 | #include "ludata.h" 4 | 5 | #include "lgc.h" 6 | #include "lmem.h" 7 | 8 | #include 9 | 10 | Udata* luaU_newudata(lua_State* L, size_t s, int tag) 11 | { 12 | if (s > INT_MAX - sizeof(Udata)) 13 | luaM_toobig(L); 14 | Udata* u = luaM_newgco(L, Udata, sizeudata(s), L->activememcat); 15 | luaC_init(L, u, LUA_TUSERDATA); 16 | u->len = int(s); 17 | u->metatable = NULL; 18 | LUAU_ASSERT(tag >= 0 && tag <= 255); 19 | u->tag = uint8_t(tag); 20 | return u; 21 | } 22 | 23 | void luaU_freeudata(lua_State* L, Udata* u, lua_Page* page) 24 | { 25 | if (u->tag < LUA_UTAG_LIMIT) 26 | { 27 | lua_Destructor dtor = L->global->udatagc[u->tag]; 28 | // TODO: access to L here is highly unsafe since this is called during internal GC traversal 29 | // certain operations such as lua_getthreaddata are okay, but by and large this risks crashes on improper use 30 | if (dtor) 31 | dtor(L, u->data); 32 | } 33 | else if (u->tag == UTAG_IDTOR) 34 | { 35 | void (*dtor)(void*) = nullptr; 36 | memcpy(&dtor, &u->data + u->len - sizeof(dtor), sizeof(dtor)); 37 | if (dtor) 38 | dtor(u->data); 39 | } 40 | 41 | 42 | luaM_freegco(L, u, sizeudata(u->len), u->memcat, page); 43 | } 44 | -------------------------------------------------------------------------------- /VM/src/ludata.h: -------------------------------------------------------------------------------- 1 | // This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | // This code is based on Lua 5.x implementation licensed under MIT License; see lua_LICENSE.txt for details 3 | #pragma once 4 | 5 | #include "lobject.h" 6 | 7 | // special tag value is used for user data with inline dtors 8 | #define UTAG_IDTOR LUA_UTAG_LIMIT 9 | 10 | // special tag value is used for newproxy-created user data (all other user data objects are host-exposed) 11 | #define UTAG_PROXY (LUA_UTAG_LIMIT + 1) 12 | 13 | // userdata larger than 16 bytes will be extended to guarantee 16 byte alignment of subsequent blocks 14 | #define sizeudata(len) (offsetof(Udata, data) + (len > 16 ? ((len + 15) & ~15) : len)) 15 | 16 | LUAI_FUNC Udata* luaU_newudata(lua_State* L, size_t s, int tag); 17 | LUAI_FUNC void luaU_freeudata(lua_State* L, Udata* u, struct lua_Page* page); 18 | -------------------------------------------------------------------------------- /bench/color.py: -------------------------------------------------------------------------------- 1 | # This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | from enum import Enum 3 | import sys 4 | 5 | class Color(Enum): 6 | DEFAULT = 0 7 | RED = 1 8 | GREEN = 2 9 | BLUE = 3 10 | YELLOW = 4 11 | WHITE = 5 12 | 13 | def colored_on(color:Color, message:str): 14 | from colorama import Fore, Style 15 | color_mappings = { 16 | Color.DEFAULT: (Fore.WHITE, Style.NORMAL), 17 | Color.RED: (Fore.RED, Style.NORMAL), 18 | Color.GREEN: (Fore.GREEN, Style.NORMAL), 19 | Color.BLUE: (Fore.BLUE, Style.BRIGHT), 20 | Color.YELLOW: (Fore.YELLOW, Style.NORMAL), 21 | Color.WHITE: (Fore.WHITE, Style.BRIGHT) 22 | } 23 | fore, style = color_mappings[color] 24 | return fore + style + message + Style.RESET_ALL 25 | 26 | def colored_off(color:Color, message:str): 27 | return message 28 | 29 | try: 30 | if sys.stdout.isatty(): 31 | import colorama 32 | colorama.init() 33 | colored = colored_on 34 | else: 35 | colored = colored_off 36 | except: 37 | colored = colored_off 38 | -------------------------------------------------------------------------------- /bench/gc/test_BinaryTree.lua: -------------------------------------------------------------------------------- 1 | local function prequire(name) local success, result = pcall(require, name); return success and result end 2 | local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") 3 | 4 | function test() 5 | 6 | -- The Computer Language Benchmarks Game 7 | -- http://benchmarksgame.alioth.debian.org/ 8 | -- contributed by Mike Pall 9 | 10 | local function BottomUpTree(item, depth) 11 | if depth > 0 then 12 | local i = item + item 13 | depth = depth - 1 14 | local left, right = BottomUpTree(i-1, depth), BottomUpTree(i, depth) 15 | return { item, left, right } 16 | else 17 | return { item } 18 | end 19 | end 20 | 21 | local function ItemCheck(tree) 22 | if tree[2] then 23 | return tree[1] + ItemCheck(tree[2]) - ItemCheck(tree[3]) 24 | else 25 | return tree[1] 26 | end 27 | end 28 | 29 | local N = 10 30 | local mindepth = 4 31 | local maxdepth = mindepth + 2 32 | if maxdepth < N then maxdepth = N end 33 | 34 | local ts0 = os.clock() 35 | 36 | do 37 | local stretchdepth = maxdepth + 1 38 | local stretchtree = BottomUpTree(0, stretchdepth) 39 | end 40 | 41 | local longlivedtree = BottomUpTree(0, maxdepth) 42 | 43 | for depth=mindepth,maxdepth,2 do 44 | local iterations = 2 ^ (maxdepth - depth + mindepth) 45 | local check = 0 46 | for i=1,iterations do 47 | check = check + ItemCheck(BottomUpTree(1, depth)) + 48 | ItemCheck(BottomUpTree(-1, depth)) 49 | end 50 | end 51 | 52 | local ts1 = os.clock() 53 | 54 | return ts1 - ts0 55 | end 56 | 57 | bench.runCode(test, "BinaryTree") -------------------------------------------------------------------------------- /bench/gc/test_GC_Tree_Pruning_Eager.lua: -------------------------------------------------------------------------------- 1 | local function prequire(name) local success, result = pcall(require, name); return success and result end 2 | local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") 3 | 4 | function test() 5 | local count = 1 6 | 7 | local function fill_tree(tree, levels) 8 | if not tree.left then 9 | tree.left = { id = count } 10 | count = count + 1 11 | end 12 | 13 | if not tree.right then 14 | tree.right = { id = count } 15 | count = count + 1 16 | end 17 | 18 | if levels ~= 0 then 19 | fill_tree(tree.left, levels - 1) 20 | fill_tree(tree.right, levels - 1) 21 | end 22 | end 23 | 24 | local function prune_tree(tree, level) 25 | if tree.left then 26 | if math.random() > 0.9 - level * 0.05 then 27 | tree.left = nil 28 | else 29 | prune_tree(tree.left, level + 1) 30 | end 31 | end 32 | 33 | if tree.right then 34 | if math.random() > 0.9 - level * 0.05 then 35 | tree.right = nil 36 | else 37 | prune_tree(tree.right, level + 1) 38 | end 39 | end 40 | end 41 | 42 | local tree = { id = 0 } 43 | 44 | for i = 1,100 do 45 | fill_tree(tree, 10) 46 | 47 | prune_tree(tree, 0) 48 | end 49 | end 50 | 51 | bench.runCode(test, "GC: tree pruning (eager fill)") 52 | -------------------------------------------------------------------------------- /bench/gc/test_GC_Tree_Pruning_Gen.lua: -------------------------------------------------------------------------------- 1 | local function prequire(name) local success, result = pcall(require, name); return success and result end 2 | local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") 3 | 4 | function test() 5 | local count = 1 6 | 7 | local function fill_tree(tree, levels) 8 | if not tree.left then 9 | tree.left = { id = count } 10 | count = count + 1 11 | end 12 | 13 | if not tree.right then 14 | tree.right = { id = count } 15 | count = count + 1 16 | end 17 | 18 | if levels ~= 0 then 19 | fill_tree(tree.left, levels - 1) 20 | fill_tree(tree.right, levels - 1) 21 | end 22 | end 23 | 24 | local function prune_tree(tree, level) 25 | if tree.left then 26 | if math.random() > 0.9 - level * 0.05 then 27 | tree.left = nil 28 | else 29 | prune_tree(tree.left, level + 1) 30 | end 31 | end 32 | 33 | if tree.right then 34 | if math.random() > 0.9 - level * 0.05 then 35 | tree.right = nil 36 | else 37 | prune_tree(tree.right, level + 1) 38 | end 39 | end 40 | end 41 | 42 | -- create a static tree 43 | local tree = { id = 0 } 44 | fill_tree(tree, 16) 45 | 46 | for i = 1,100 do 47 | local small_tree = { id = 0 } 48 | 49 | fill_tree(small_tree, 8) 50 | 51 | prune_tree(small_tree, 0) 52 | end 53 | end 54 | 55 | bench.runCode(test, "GC: tree pruning (eager fill, gen)") 56 | -------------------------------------------------------------------------------- /bench/gc/test_GC_Tree_Pruning_Lazy.lua: -------------------------------------------------------------------------------- 1 | local function prequire(name) local success, result = pcall(require, name); return success and result end 2 | local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") 3 | 4 | function test() 5 | local count = 1 6 | 7 | local function fill_tree(tree, levels) 8 | local left = tree.left; 9 | local right = tree.right; 10 | 11 | if not left then 12 | left = { id = count } 13 | count = count + 1 14 | end 15 | 16 | if not right then 17 | right = { id = count } 18 | count = count + 1 19 | end 20 | 21 | if levels ~= 0 then 22 | fill_tree(left, levels - 1) 23 | fill_tree(right, levels - 1) 24 | end 25 | 26 | tree.left = left; 27 | tree.right = right; 28 | end 29 | 30 | local function prune_tree(tree, level) 31 | if tree.left then 32 | if math.random() > 0.9 - level * 0.05 then 33 | tree.left = nil 34 | else 35 | prune_tree(tree.left, level + 1) 36 | end 37 | end 38 | 39 | if tree.right then 40 | if math.random() > 0.9 - level * 0.05 then 41 | tree.right = nil 42 | else 43 | prune_tree(tree.right, level + 1) 44 | end 45 | end 46 | end 47 | 48 | local tree = { id = 0 } 49 | 50 | for i = 1,100 do 51 | fill_tree(tree, 10) 52 | 53 | prune_tree(tree, 0) 54 | end 55 | end 56 | 57 | bench.runCode(test, "GC: tree pruning (lazy fill)") 58 | -------------------------------------------------------------------------------- /bench/gc/test_GC_hashtable_Keyval.lua: -------------------------------------------------------------------------------- 1 | local function prequire(name) local success, result = pcall(require, name); return success and result end 2 | local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") 3 | 4 | function test() 5 | local t = {} 6 | 7 | local max = 10000 8 | local iters = 50000 9 | 10 | for i = 1,iters do 11 | local is = tostring(i) 12 | local input = string.rep(is, 1000 / #is) 13 | 14 | t[is] = input 15 | 16 | -- remove old entries 17 | if i > max then 18 | t[tostring(i - max)] = nil 19 | end 20 | end 21 | end 22 | 23 | bench.runCode(test, "GC: hashtable keys and values") 24 | -------------------------------------------------------------------------------- /bench/gc/test_LargeTableCtor_hash.lua: -------------------------------------------------------------------------------- 1 | local function prequire(name) local success, result = pcall(require, name); return success and result end 2 | local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") 3 | 4 | function test() 5 | 6 | local ts0 = os.clock() 7 | for i=1,100000 do 8 | local t = { a = 1, b = 2, c = 3, d = 4, e = 5, f = 6 } 9 | end 10 | local ts1 = os.clock() 11 | 12 | return ts1-ts0 13 | end 14 | 15 | bench.runCode(test, "LargeTableCtor: hash") -------------------------------------------------------------------------------- /bench/gc/test_Pcall_pcall_yield.lua: -------------------------------------------------------------------------------- 1 | local function prequire(name) local success, result = pcall(require, name); return success and result end 2 | local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") 3 | 4 | function test() 5 | 6 | function test() coroutine.yield() return 1 end 7 | 8 | local ts0 = os.clock() 9 | for i=0,100000 do 10 | local co = coroutine.create(function() return pcall(test) end) 11 | coroutine.resume(co) 12 | coroutine.resume(co) 13 | end 14 | local ts1 = os.clock() 15 | 16 | return ts1-ts0 17 | end 18 | 19 | bench.runCode(test, "Pcall: pcall yield") -------------------------------------------------------------------------------- /bench/gc/test_TableCreate_nil.lua: -------------------------------------------------------------------------------- 1 | local function prequire(name) local success, result = pcall(require, name); return success and result end 2 | local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") 3 | 4 | function test() 5 | 6 | local ts0 = os.clock() 7 | for i=1,100000 do table.create(100) end 8 | local ts1 = os.clock() 9 | 10 | return ts1-ts0 11 | end 12 | 13 | bench.runCode(test, "TableCreate: nil") -------------------------------------------------------------------------------- /bench/gc/test_TableCreate_number.lua: -------------------------------------------------------------------------------- 1 | local function prequire(name) local success, result = pcall(require, name); return success and result end 2 | local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") 3 | 4 | function test() 5 | 6 | local ts0 = os.clock() 7 | for i=1,100000 do table.create(100,0) end 8 | local ts1 = os.clock() 9 | 10 | return ts1-ts0 11 | end 12 | 13 | bench.runCode(test, "TableCreate: number") -------------------------------------------------------------------------------- /bench/gc/test_TableCreate_zerofill.lua: -------------------------------------------------------------------------------- 1 | local function prequire(name) local success, result = pcall(require, name); return success and result end 2 | local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") 3 | 4 | function test() 5 | 6 | local ts0 = os.clock() 7 | for i=1,100000 do 8 | local t = table.create(100) 9 | for j=1,100 do t[j] = 0 end 10 | end 11 | local ts1 = os.clock() 12 | 13 | return ts1-ts0 14 | end 15 | 16 | bench.runCode(test, "TableCreate: zerofill") -------------------------------------------------------------------------------- /bench/gc/test_TableMarshal_select.lua: -------------------------------------------------------------------------------- 1 | local function prequire(name) local success, result = pcall(require, name); return success and result end 2 | local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") 3 | 4 | function test() 5 | 6 | local function pack(...) 7 | return {n = select('#', ...), ...} 8 | end 9 | 10 | local ts0 = os.clock() 11 | 12 | for i=1,100000 do 13 | local t = pack(1,2,3,4,5,6,7,8,9,10) 14 | end 15 | 16 | local ts1 = os.clock() 17 | 18 | return ts1-ts0 19 | end 20 | 21 | bench.runCode(test, "TableMarshal: {n=select,...}") -------------------------------------------------------------------------------- /bench/gc/test_TableMarshal_table_pack.lua: -------------------------------------------------------------------------------- 1 | local function prequire(name) local success, result = pcall(require, name); return success and result end 2 | local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") 3 | 4 | function test() 5 | 6 | local function pack(...) 7 | return table.pack(...) 8 | end 9 | 10 | local ts0 = os.clock() 11 | 12 | for i=1,100000 do 13 | local t = pack(1,2,3,4,5,6,7,8,9,10) 14 | end 15 | 16 | local ts1 = os.clock() 17 | 18 | return ts1-ts0 19 | end 20 | 21 | bench.runCode(test, "TableMarshal: table.pack") -------------------------------------------------------------------------------- /bench/gc/test_TableMarshal_varargs.lua: -------------------------------------------------------------------------------- 1 | local function prequire(name) local success, result = pcall(require, name); return success and result end 2 | local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") 3 | 4 | function test() 5 | 6 | local function pack(...) 7 | return {...} 8 | end 9 | 10 | local ts0 = os.clock() 11 | 12 | for i=1,100000 do 13 | local t = pack(1,2,3,4,5,6,7,8,9,10) 14 | end 15 | 16 | local ts1 = os.clock() 17 | 18 | return ts1-ts0 19 | end 20 | 21 | bench.runCode(test, "TableMarshal: {...}") -------------------------------------------------------------------------------- /bench/install.bat: -------------------------------------------------------------------------------- 1 | python -m pip install matplotlib 2 | python -m pip install scipy 3 | python -m pip install requests 4 | -------------------------------------------------------------------------------- /bench/install.sh: -------------------------------------------------------------------------------- 1 | python -m pip install matplotlib 2 | python -m pip install scipy 3 | python -m pip install requests 4 | -------------------------------------------------------------------------------- /bench/measure_time.py: -------------------------------------------------------------------------------- 1 | # This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | import os, sys, time, numpy 3 | 4 | try: 5 | import scipy 6 | from scipy import mean, stats 7 | except ModuleNotFoundError: 8 | print("Warning: scipy package is not installed, confidence values will not be available") 9 | stats = None 10 | 11 | duration_list = [] 12 | 13 | DEFAULT_CYCLES_TO_RUN = 100 14 | cycles_to_run = DEFAULT_CYCLES_TO_RUN 15 | 16 | try: 17 | cycles_to_run = sys.argv[3] if sys.argv[3] else DEFAULT_CYCLES_TO_RUN 18 | cycles_to_run = int(cycles_to_run) 19 | except IndexError: 20 | pass 21 | except (ValueError, TypeError): 22 | cycles_to_run = DEFAULT_CYCLES_TO_RUN 23 | print("Error: Cycles to run argument must be an integer. Using default value of {}".format(DEFAULT_CYCLES_TO_RUN)) 24 | 25 | # Numpy complains if we provide a cycle count of less than 3 ~ default to 3 whenever a lower value is provided 26 | cycles_to_run = cycles_to_run if cycles_to_run > 2 else 3 27 | 28 | for i in range(1,cycles_to_run): 29 | start = time.perf_counter() 30 | 31 | # Run the code you want to measure here 32 | os.system(sys.argv[1]) 33 | 34 | end = time.perf_counter() 35 | 36 | duration_ms = (end - start) * 1000 37 | duration_list.append(duration_ms) 38 | 39 | # Stats 40 | mean = numpy.mean(duration_list) 41 | std_err = stats.sem(duration_list) 42 | 43 | print("SUCCESS: {} : {:.2f}ms +/- {:.2f}% on luau ".format('duration', mean,std_err)) 44 | -------------------------------------------------------------------------------- /bench/micro_tests/test_AbsSum_abs.lua: -------------------------------------------------------------------------------- 1 | local function prequire(name) local success, result = pcall(require, name); return success and result end 2 | local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") 3 | 4 | function test() 5 | 6 | local abs = math.abs 7 | local ts0 = os.clock() 8 | local sum = 0 9 | for i=-500000,500000 do sum = sum + abs(i) end 10 | local ts1 = os.clock() 11 | 12 | return ts1-ts0 13 | end 14 | 15 | bench.runCode(test, "AbsSum: abs") -------------------------------------------------------------------------------- /bench/micro_tests/test_AbsSum_and_or.lua: -------------------------------------------------------------------------------- 1 | local function prequire(name) local success, result = pcall(require, name); return success and result end 2 | local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") 3 | 4 | function test() 5 | 6 | local ts0 = os.clock() 7 | local sum = 0 8 | for i=-500000,500000 do sum = sum + (i < 0 and -i or i) end 9 | local ts1 = os.clock() 10 | 11 | return ts1-ts0 12 | end 13 | 14 | bench.runCode(test, "AbsSum: and/or") -------------------------------------------------------------------------------- /bench/micro_tests/test_AbsSum_math_abs.lua: -------------------------------------------------------------------------------- 1 | local function prequire(name) local success, result = pcall(require, name); return success and result end 2 | local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") 3 | 4 | function test() 5 | 6 | local ts0 = os.clock() 7 | local sum = 0 8 | for i=-500000,500000 do sum = sum + math.abs(i) end 9 | local ts1 = os.clock() 10 | 11 | return ts1-ts0 12 | end 13 | 14 | bench.runCode(test, "AbsSum: math.abs") -------------------------------------------------------------------------------- /bench/micro_tests/test_Assert.lua: -------------------------------------------------------------------------------- 1 | local function prequire(name) local success, result = pcall(require, name); return success and result end 2 | local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") 3 | 4 | function test() 5 | 6 | local ts0 = os.clock() 7 | for i=-500000,500000 do assert(i) end 8 | local ts1 = os.clock() 9 | 10 | return ts1-ts0 11 | end 12 | 13 | bench.runCode(test, "Assert") -------------------------------------------------------------------------------- /bench/micro_tests/test_Factorial.lua: -------------------------------------------------------------------------------- 1 | local function prequire(name) local success, result = pcall(require, name); return success and result end 2 | local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") 3 | 4 | function test() 5 | 6 | function fact (n) 7 | if n == 0 then 8 | return 1 9 | else 10 | return n * fact(n-1) 11 | end 12 | end 13 | 14 | local ts0 = os.clock() 15 | for loops=1,500 do 16 | for i=1,100 do 17 | fact(i) 18 | end 19 | end 20 | local ts1 = os.clock() 21 | 22 | return ts1 - ts0 23 | end 24 | 25 | bench.runCode(test, "Factorial") -------------------------------------------------------------------------------- /bench/micro_tests/test_Failure_pcall_a_bar.lua: -------------------------------------------------------------------------------- 1 | local function prequire(name) local success, result = pcall(require, name); return success and result end 2 | local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") 3 | 4 | function test() 5 | 6 | function test(a) return a.bar end 7 | 8 | local ts0 = os.clock() 9 | for i=0,10000 do pcall(test) end 10 | local ts1 = os.clock() 11 | 12 | return ts1-ts0 13 | end 14 | 15 | bench.runCode(test, "Failure: pcall a.bar") -------------------------------------------------------------------------------- /bench/micro_tests/test_Failure_pcall_game_Foo.lua: -------------------------------------------------------------------------------- 1 | local function prequire(name) local success, result = pcall(require, name); return success and result end 2 | local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") 3 | 4 | function test() 5 | 6 | function test() return game.Foo end 7 | 8 | local ts0 = os.clock() 9 | for i=0,10000 do pcall(test) end 10 | local ts1 = os.clock() 11 | 12 | return ts1-ts0 13 | end 14 | 15 | bench.runCode(test, "Failure: pcall game.Foo") -------------------------------------------------------------------------------- /bench/micro_tests/test_Failure_xpcall_a_bar.lua: -------------------------------------------------------------------------------- 1 | local function prequire(name) local success, result = pcall(require, name); return success and result end 2 | local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") 3 | 4 | function test() 5 | 6 | function test(a) return a.bar end 7 | function err(e) return e end 8 | 9 | local ts0 = os.clock() 10 | for i=0,10000 do xpcall(test, err) end 11 | local ts1 = os.clock() 12 | 13 | return ts1-ts0 14 | end 15 | 16 | bench.runCode(test, "Failure: xpcall a.bar") -------------------------------------------------------------------------------- /bench/micro_tests/test_Failure_xpcall_game_Foo.lua: -------------------------------------------------------------------------------- 1 | local function prequire(name) local success, result = pcall(require, name); return success and result end 2 | local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") 3 | 4 | function test() 5 | 6 | function test() return game.Foo end 7 | function err(e) return e end 8 | 9 | local ts0 = os.clock() 10 | for i=0,10000 do xpcall(test, err) end 11 | local ts1 = os.clock() 12 | 13 | return ts1-ts0 14 | end 15 | 16 | bench.runCode(test, "Failure: xpcall game.Foo") -------------------------------------------------------------------------------- /bench/micro_tests/test_LargeTableCtor_hash.lua: -------------------------------------------------------------------------------- 1 | local function prequire(name) local success, result = pcall(require, name); return success and result end 2 | local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") 3 | 4 | function test() 5 | 6 | local ts0 = os.clock() 7 | for i=1,100000 do 8 | local t = { a = 1, b = 2, c = 3, d = 4, e = 5, f = 6 } 9 | end 10 | local ts1 = os.clock() 11 | 12 | return ts1-ts0 13 | end 14 | 15 | bench.runCode(test, "LargeTableCtor: hash") -------------------------------------------------------------------------------- /bench/micro_tests/test_LargeTableSum_loop_index.lua: -------------------------------------------------------------------------------- 1 | local function prequire(name) local success, result = pcall(require, name); return success and result end 2 | local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") 3 | 4 | function test() 5 | 6 | local t = {} 7 | 8 | for i=1,1000000 do t[i] = i end 9 | 10 | local ts0 = os.clock() 11 | local sum = 0 12 | for i=1,#t do sum = sum + t[i] end 13 | local ts1 = os.clock() 14 | 15 | return ts1-ts0 16 | end 17 | 18 | bench.runCode(test, "LargeTableSum: for i=1,#t") -------------------------------------------------------------------------------- /bench/micro_tests/test_LargeTableSum_loop_ipairs.lua: -------------------------------------------------------------------------------- 1 | local function prequire(name) local success, result = pcall(require, name); return success and result end 2 | local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") 3 | 4 | function test() 5 | 6 | local t = {} 7 | 8 | for i=1,1000000 do t[i] = i end 9 | 10 | local ts0 = os.clock() 11 | local sum = 0 12 | for k,v in ipairs(t) do sum = sum + v end 13 | local ts1 = os.clock() 14 | 15 | return ts1-ts0 16 | end 17 | 18 | bench.runCode(test, "LargeTableSum: for k,v in ipairs") -------------------------------------------------------------------------------- /bench/micro_tests/test_LargeTableSum_loop_iter.lua: -------------------------------------------------------------------------------- 1 | local function prequire(name) local success, result = pcall(require, name); return success and result end 2 | local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") 3 | 4 | function test() 5 | 6 | local t = {} 7 | 8 | for i=1,1000000 do t[i] = i end 9 | 10 | local ts0 = os.clock() 11 | local sum = 0 12 | for k,v in t do sum = sum + v end 13 | local ts1 = os.clock() 14 | 15 | return ts1-ts0 16 | end 17 | 18 | bench.runCode(test, "LargeTableSum: for k,v in {}") 19 | -------------------------------------------------------------------------------- /bench/micro_tests/test_LargeTableSum_loop_pairs.lua: -------------------------------------------------------------------------------- 1 | local function prequire(name) local success, result = pcall(require, name); return success and result end 2 | local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") 3 | 4 | function test() 5 | 6 | local t = {} 7 | 8 | for i=1,1000000 do t[i] = i end 9 | 10 | local ts0 = os.clock() 11 | local sum = 0 12 | for k,v in pairs(t) do sum = sum + v end 13 | local ts1 = os.clock() 14 | 15 | return ts1-ts0 16 | end 17 | 18 | bench.runCode(test, "LargeTableSum: for k,v in pairs") -------------------------------------------------------------------------------- /bench/micro_tests/test_OOP_constructor.lua: -------------------------------------------------------------------------------- 1 | local function prequire(name) local success, result = pcall(require, name); return success and result end 2 | local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") 3 | 4 | function test() 5 | 6 | local Number = {} 7 | Number.__index = Number 8 | 9 | function Number.new(v) 10 | local self = { 11 | value = v 12 | } 13 | setmetatable(self, Number) 14 | return self 15 | end 16 | 17 | function Number:Get() 18 | return self.value 19 | end 20 | 21 | local ts0 = os.clock() 22 | for i=1,100000 do 23 | local n = Number.new(42) 24 | end 25 | local ts1 = os.clock() 26 | 27 | return ts1-ts0 28 | end 29 | 30 | bench.runCode(test, "OOP: constructor") -------------------------------------------------------------------------------- /bench/micro_tests/test_OOP_method_call.lua: -------------------------------------------------------------------------------- 1 | local function prequire(name) local success, result = pcall(require, name); return success and result end 2 | local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") 3 | 4 | function test() 5 | 6 | local Number = {} 7 | Number.__index = Number 8 | 9 | function Number.new(v) 10 | local self = { 11 | value = v 12 | } 13 | setmetatable(self, Number) 14 | return self 15 | end 16 | 17 | function Number:Get() 18 | return self.value 19 | end 20 | 21 | local n = Number.new(42) 22 | 23 | local ts0 = os.clock() 24 | for i=1,1000000 do 25 | local nv = n:Get() 26 | end 27 | local ts1 = os.clock() 28 | 29 | return ts1-ts0 30 | end 31 | 32 | bench.runCode(test, "OOP: method call") -------------------------------------------------------------------------------- /bench/micro_tests/test_OOP_virtual_constructor.lua: -------------------------------------------------------------------------------- 1 | local function prequire(name) local success, result = pcall(require, name); return success and result end 2 | local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") 3 | 4 | function test() 5 | 6 | local Number = {} 7 | Number.__index = Number 8 | 9 | function Number:new(class, v) 10 | local self = { 11 | value = v 12 | } 13 | setmetatable(self, Number) 14 | return self 15 | end 16 | 17 | function Number:Get() 18 | return self.value 19 | end 20 | 21 | local ts0 = os.clock() 22 | for i=1,100000 do 23 | local n = Number:new(42) 24 | end 25 | local ts1 = os.clock() 26 | 27 | return ts1-ts0 28 | end 29 | 30 | bench.runCode(test, "OOP: virtual constructor") -------------------------------------------------------------------------------- /bench/micro_tests/test_Pcall_call_return.lua: -------------------------------------------------------------------------------- 1 | local function prequire(name) local success, result = pcall(require, name); return success and result end 2 | local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") 3 | 4 | function test() 5 | 6 | function test() return 1 end 7 | 8 | local ts0 = os.clock() 9 | for i=0,100000 do test() end 10 | local ts1 = os.clock() 11 | 12 | return ts1-ts0 13 | end 14 | 15 | bench.runCode(test, "Pcall: call return") -------------------------------------------------------------------------------- /bench/micro_tests/test_Pcall_pcall_return.lua: -------------------------------------------------------------------------------- 1 | local function prequire(name) local success, result = pcall(require, name); return success and result end 2 | local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") 3 | 4 | function test() 5 | 6 | function test() return 1 end 7 | 8 | local ts0 = os.clock() 9 | for i=0,100000 do pcall(test) end 10 | local ts1 = os.clock() 11 | 12 | return ts1-ts0 13 | end 14 | 15 | bench.runCode(test, "Pcall: pcall return") -------------------------------------------------------------------------------- /bench/micro_tests/test_Pcall_pcall_yield.lua: -------------------------------------------------------------------------------- 1 | local function prequire(name) local success, result = pcall(require, name); return success and result end 2 | local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") 3 | 4 | function test() 5 | 6 | function test() coroutine.yield() return 1 end 7 | 8 | local ts0 = os.clock() 9 | for i=0,100000 do 10 | local co = coroutine.create(function() return pcall(test) end) 11 | coroutine.resume(co) 12 | coroutine.resume(co) 13 | end 14 | local ts1 = os.clock() 15 | 16 | return ts1-ts0 17 | end 18 | 19 | bench.runCode(test, "Pcall: pcall yield") -------------------------------------------------------------------------------- /bench/micro_tests/test_Pcall_xpcall_return.lua: -------------------------------------------------------------------------------- 1 | local function prequire(name) local success, result = pcall(require, name); return success and result end 2 | local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") 3 | 4 | function test() 5 | 6 | function test() return 1 end 7 | 8 | local ts0 = os.clock() 9 | for i=0,100000 do xpcall(test, error) end 10 | local ts1 = os.clock() 11 | 12 | return ts1-ts0 13 | end 14 | 15 | bench.runCode(test, "Pcall: xpcall return") -------------------------------------------------------------------------------- /bench/micro_tests/test_SqrtSum_exponent.lua: -------------------------------------------------------------------------------- 1 | local function prequire(name) local success, result = pcall(require, name); return success and result end 2 | local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") 3 | 4 | function test() 5 | 6 | local ts0 = os.clock() 7 | local sum = 0 8 | for i=0,500000 do sum = sum + i^0.5 end 9 | local ts1 = os.clock() 10 | 11 | return ts1-ts0 12 | end 13 | 14 | bench.runCode(test, "SqrtSum: ^0.5") -------------------------------------------------------------------------------- /bench/micro_tests/test_SqrtSum_math_sqrt.lua: -------------------------------------------------------------------------------- 1 | local function prequire(name) local success, result = pcall(require, name); return success and result end 2 | local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") 3 | 4 | function test() 5 | 6 | local ts0 = os.clock() 7 | local sum = 0 8 | for i=0,500000 do sum = sum + math.sqrt(i) end 9 | local ts1 = os.clock() 10 | 11 | return ts1-ts0 12 | end 13 | 14 | bench.runCode(test, "SqrtSum: math.sqrt") -------------------------------------------------------------------------------- /bench/micro_tests/test_SqrtSum_sqrt.lua: -------------------------------------------------------------------------------- 1 | local function prequire(name) local success, result = pcall(require, name); return success and result end 2 | local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") 3 | 4 | function test() 5 | 6 | local sqrt = math.sqrt 7 | local ts0 = os.clock() 8 | local sum = 0 9 | for i=0,500000 do sum = sum + sqrt(i) end 10 | local ts1 = os.clock() 11 | 12 | return ts1-ts0 13 | end 14 | 15 | bench.runCode(test, "SqrtSum: sqrt") -------------------------------------------------------------------------------- /bench/micro_tests/test_SqrtSum_sqrt_getfenv.lua: -------------------------------------------------------------------------------- 1 | local function prequire(name) local success, result = pcall(require, name); return success and result end 2 | local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") 3 | 4 | function test() 5 | 6 | local sqrt = math.sqrt 7 | getfenv() 8 | local ts0 = os.clock() 9 | local sum = 0 10 | for i=0,500000 do sum = sum + sqrt(i) end 11 | local ts1 = os.clock() 12 | 13 | return ts1-ts0 14 | end 15 | 16 | bench.runCode(test, "SqrtSum: sqrt getfenv") -------------------------------------------------------------------------------- /bench/micro_tests/test_SqrtSum_sqrt_roundabout.lua: -------------------------------------------------------------------------------- 1 | local function prequire(name) local success, result = pcall(require, name); return success and result end 2 | local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") 3 | 4 | function test() 5 | 6 | local sqrt = nil or math.sqrt -- breaks fastcall analysis 7 | local ts0 = os.clock() 8 | local sum = 0 9 | for i=0,500000 do sum = sum + sqrt(i) end 10 | local ts1 = os.clock() 11 | 12 | return ts1-ts0 13 | end 14 | 15 | bench.runCode(test, "SqrtSum: sqrt roundabout") -------------------------------------------------------------------------------- /bench/micro_tests/test_StringInterp.lua: -------------------------------------------------------------------------------- 1 | local function prequire(name) local success, result = pcall(require, name); return success and result end 2 | local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") 3 | 4 | bench.runCode(function() 5 | for j=1,1e6 do 6 | local _ = "j=" .. tostring(j) 7 | end 8 | end, "interp: tostring") 9 | 10 | bench.runCode(function() 11 | for j=1,1e6 do 12 | local _ = "j=" .. j 13 | end 14 | end, "interp: concat") 15 | 16 | bench.runCode(function() 17 | for j=1,1e6 do 18 | local _ = string.format("j=%f", j) 19 | end 20 | end, "interp: %f format") 21 | 22 | bench.runCode(function() 23 | for j=1,1e6 do 24 | local _ = string.format("j=%d", j) 25 | end 26 | end, "interp: %d format") 27 | 28 | bench.runCode(function() 29 | for j=1,1e6 do 30 | local _ = string.format("j=%*", j) 31 | end 32 | end, "interp: %* format") 33 | 34 | bench.runCode(function() 35 | for j=1,1e6 do 36 | local _ = `j={j}` 37 | end 38 | end, "interp: interp number") 39 | 40 | bench.runCode(function() 41 | local ok = "hello!" 42 | for j=1,1e6 do 43 | local _ = string.format("j=%s", ok) 44 | end 45 | end, "interp: %s format") 46 | 47 | bench.runCode(function() 48 | local ok = "hello!" 49 | for j=1,1e6 do 50 | local _ = `j={ok}` 51 | end 52 | end, "interp: interp string") -------------------------------------------------------------------------------- /bench/micro_tests/test_TableCreate_nil.lua: -------------------------------------------------------------------------------- 1 | local function prequire(name) local success, result = pcall(require, name); return success and result end 2 | local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") 3 | 4 | function test() 5 | 6 | local ts0 = os.clock() 7 | for i=1,100000 do table.create(100) end 8 | local ts1 = os.clock() 9 | 10 | return ts1-ts0 11 | end 12 | 13 | bench.runCode(test, "TableCreate: nil") -------------------------------------------------------------------------------- /bench/micro_tests/test_TableCreate_number.lua: -------------------------------------------------------------------------------- 1 | local function prequire(name) local success, result = pcall(require, name); return success and result end 2 | local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") 3 | 4 | function test() 5 | 6 | local ts0 = os.clock() 7 | for i=1,100000 do table.create(100,0) end 8 | local ts1 = os.clock() 9 | 10 | return ts1-ts0 11 | end 12 | 13 | bench.runCode(test, "TableCreate: number") -------------------------------------------------------------------------------- /bench/micro_tests/test_TableCreate_zerofill.lua: -------------------------------------------------------------------------------- 1 | local function prequire(name) local success, result = pcall(require, name); return success and result end 2 | local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") 3 | 4 | function test() 5 | 6 | local ts0 = os.clock() 7 | for i=1,100000 do 8 | local t = table.create(100) 9 | for j=1,100 do t[j] = 0 end 10 | end 11 | local ts1 = os.clock() 12 | 13 | return ts1-ts0 14 | end 15 | 16 | bench.runCode(test, "TableCreate: zerofill") -------------------------------------------------------------------------------- /bench/micro_tests/test_TableFind_loop_ipairs.lua: -------------------------------------------------------------------------------- 1 | local function prequire(name) local success, result = pcall(require, name); return success and result end 2 | local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") 3 | 4 | function test() 5 | 6 | local function find(t, v) 7 | for i,e in ipairs(t) do 8 | if e == v then 9 | return i 10 | end 11 | end 12 | 13 | return nil 14 | end 15 | 16 | local t = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20} 17 | 18 | local ts0 = os.clock() 19 | for i=1,100000 do find(t,15) end 20 | local ts1 = os.clock() 21 | 22 | return ts1-ts0 23 | end 24 | 25 | bench.runCode(test, "TableFind: for+ipairs") -------------------------------------------------------------------------------- /bench/micro_tests/test_TableFind_table_find.lua: -------------------------------------------------------------------------------- 1 | local function prequire(name) local success, result = pcall(require, name); return success and result end 2 | local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") 3 | 4 | function test() 5 | 6 | local t = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20} 7 | 8 | local ts0 = os.clock() 9 | for i=1,100000 do table.find(t,15) end 10 | local ts1 = os.clock() 11 | 12 | return ts1-ts0 13 | end 14 | 15 | bench.runCode(test, "TableFind: table.find") -------------------------------------------------------------------------------- /bench/micro_tests/test_TableInsertion_index_cached.lua: -------------------------------------------------------------------------------- 1 | local function prequire(name) local success, result = pcall(require, name); return success and result end 2 | local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") 3 | 4 | function test() 5 | 6 | local ts0 = os.clock() 7 | 8 | for i=1,300 do 9 | local t = {} 10 | for j=1,1000 do 11 | t[j] = j 12 | end 13 | end 14 | 15 | local ts1 = os.clock() 16 | 17 | return ts1-ts0 18 | end 19 | 20 | bench.runCode(test, "TableInsertion: t[i]") -------------------------------------------------------------------------------- /bench/micro_tests/test_TableInsertion_index_len.lua: -------------------------------------------------------------------------------- 1 | local function prequire(name) local success, result = pcall(require, name); return success and result end 2 | local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") 3 | 4 | function test() 5 | 6 | local ts0 = os.clock() 7 | 8 | for i=1,300 do 9 | local t = {} 10 | for j=1,1000 do 11 | t[#t+1] = j 12 | end 13 | end 14 | 15 | local ts1 = os.clock() 16 | 17 | return ts1-ts0 18 | end 19 | 20 | bench.runCode(test, "TableInsertion: t[#t+1]") -------------------------------------------------------------------------------- /bench/micro_tests/test_TableInsertion_table_insert.lua: -------------------------------------------------------------------------------- 1 | local function prequire(name) local success, result = pcall(require, name); return success and result end 2 | local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") 3 | 4 | function test() 5 | 6 | local ts0 = os.clock() 7 | 8 | for i=1,300 do 9 | local t = {} 10 | for j=1,1000 do 11 | table.insert(t, j) 12 | end 13 | end 14 | 15 | local ts1 = os.clock() 16 | 17 | return ts1-ts0 18 | end 19 | 20 | bench.runCode(test, "TableInsertion: table.insert") -------------------------------------------------------------------------------- /bench/micro_tests/test_TableInsertion_table_insert_index.lua: -------------------------------------------------------------------------------- 1 | local function prequire(name) local success, result = pcall(require, name); return success and result end 2 | local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") 3 | 4 | function test() 5 | 6 | local ts0 = os.clock() 7 | 8 | for i=1,5 do 9 | local t = {} 10 | for j=1,1000 do 11 | table.insert(t, 1, j) 12 | end 13 | end 14 | 15 | local ts1 = os.clock() 16 | 17 | for i=1,5 do 18 | local t = {} 19 | for j=1,1000 do 20 | table.insert(t, 1, j) 21 | end 22 | 23 | for j=1,1000 do 24 | assert(t[j] == (1000- (j - 1) ) ) 25 | end 26 | end 27 | 28 | return ts1-ts0 29 | end 30 | 31 | bench.runCode(test, "TableInsertion: table.insert(pos)") -------------------------------------------------------------------------------- /bench/micro_tests/test_TableIteration.lua: -------------------------------------------------------------------------------- 1 | local function prequire(name) local success, result = pcall(require, name); return success and result end 2 | local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") 3 | 4 | function test() 5 | 6 | local t = {} 7 | 8 | for i=1,100 do t[tostring(i)] = i end 9 | 10 | local ts0 = os.clock() 11 | local sum = 0 12 | for i=1,10000 do 13 | for k,v in pairs(t) do sum = sum + v end 14 | end 15 | local ts1 = os.clock() 16 | 17 | return ts1-ts0 18 | end 19 | 20 | bench.runCode(test, "TableIteration") -------------------------------------------------------------------------------- /bench/micro_tests/test_TableMarshal_select.lua: -------------------------------------------------------------------------------- 1 | local function prequire(name) local success, result = pcall(require, name); return success and result end 2 | local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") 3 | 4 | function test() 5 | 6 | local function pack(...) 7 | return {n = select('#', ...), ...} 8 | end 9 | 10 | local ts0 = os.clock() 11 | 12 | for i=1,100000 do 13 | local t = pack(1,2,3,4,5,6,7,8,9,10) 14 | end 15 | 16 | local ts1 = os.clock() 17 | 18 | return ts1-ts0 19 | end 20 | 21 | bench.runCode(test, "TableMarshal: {n=select,...}") -------------------------------------------------------------------------------- /bench/micro_tests/test_TableMarshal_table_pack.lua: -------------------------------------------------------------------------------- 1 | local function prequire(name) local success, result = pcall(require, name); return success and result end 2 | local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") 3 | 4 | function test() 5 | 6 | local function pack(...) 7 | return table.pack(...) 8 | end 9 | 10 | local ts0 = os.clock() 11 | 12 | for i=1,100000 do 13 | local t = pack(1,2,3,4,5,6,7,8,9,10) 14 | end 15 | 16 | local ts1 = os.clock() 17 | 18 | return ts1-ts0 19 | end 20 | 21 | bench.runCode(test, "TableMarshal: table.pack") -------------------------------------------------------------------------------- /bench/micro_tests/test_TableMarshal_table_unpack_array.lua: -------------------------------------------------------------------------------- 1 | local function prequire(name) local success, result = pcall(require, name); return success and result end 2 | local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") 3 | 4 | function test() 5 | 6 | local function consume(...) 7 | end 8 | 9 | local t = {1,2,3,4,5,6,7,8,9,10} 10 | 11 | local ts0 = os.clock() 12 | 13 | for i=1,1000000 do 14 | consume(table.unpack(t)) 15 | end 16 | 17 | local ts1 = os.clock() 18 | 19 | return ts1-ts0 20 | end 21 | 22 | bench.runCode(test, "TableMarshal: table.unpack") -------------------------------------------------------------------------------- /bench/micro_tests/test_TableMarshal_table_unpack_range.lua: -------------------------------------------------------------------------------- 1 | local function prequire(name) local success, result = pcall(require, name); return success and result end 2 | local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") 3 | 4 | function test() 5 | 6 | local function consume(...) 7 | end 8 | 9 | local t = {n=10,1,2,3,4,5,6,7,8,9,10} 10 | 11 | local ts0 = os.clock() 12 | 13 | for i=1,1000000 do 14 | consume(table.unpack(t, 1, t.n)) 15 | end 16 | 17 | local ts1 = os.clock() 18 | 19 | return ts1-ts0 20 | end 21 | 22 | bench.runCode(test, "TableMarshal: table.unpack/n") -------------------------------------------------------------------------------- /bench/micro_tests/test_TableMarshal_varargs.lua: -------------------------------------------------------------------------------- 1 | local function prequire(name) local success, result = pcall(require, name); return success and result end 2 | local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") 3 | 4 | function test() 5 | 6 | local function pack(...) 7 | return {...} 8 | end 9 | 10 | local ts0 = os.clock() 11 | 12 | for i=1,100000 do 13 | local t = pack(1,2,3,4,5,6,7,8,9,10) 14 | end 15 | 16 | local ts1 = os.clock() 17 | 18 | return ts1-ts0 19 | end 20 | 21 | bench.runCode(test, "TableMarshal: {...}") -------------------------------------------------------------------------------- /bench/micro_tests/test_TableMove_empty_table.lua: -------------------------------------------------------------------------------- 1 | local function prequire(name) local success, result = pcall(require, name); return success and result end 2 | local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") 3 | 4 | function test() 5 | local t = table.create(250001, 0) 6 | 7 | for i=1,250000 do 8 | t[i] = i 9 | end 10 | 11 | local t2 = {} 12 | 13 | local ts0 = os.clock() 14 | table.move(t, 1, 250000, 1, t2) 15 | local ts1 = os.clock() 16 | 17 | for i=1,250000-1 do 18 | assert(t2[i] == i) 19 | end 20 | 21 | return ts1-ts0 22 | end 23 | 24 | bench.runCode(test, "TableMove: {}") 25 | -------------------------------------------------------------------------------- /bench/micro_tests/test_TableMove_same_table.lua: -------------------------------------------------------------------------------- 1 | local function prequire(name) local success, result = pcall(require, name); return success and result end 2 | local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") 3 | 4 | function test() 5 | local t = table.create(5000001, 0) 6 | 7 | for i=0,5000000 do 8 | t[i] = i 9 | end 10 | 11 | local ts0 = os.clock() 12 | table.move(t, 1, 250000, 250001, t) 13 | local ts1 = os.clock() 14 | 15 | for i=250001,(500000-1) do 16 | assert(t[i] == (i - 250001) + 1) 17 | end 18 | 19 | return ts1-ts0 20 | end 21 | 22 | bench.runCode(test, "TableMove: same table") 23 | -------------------------------------------------------------------------------- /bench/micro_tests/test_TableMove_table_create.lua: -------------------------------------------------------------------------------- 1 | local function prequire(name) local success, result = pcall(require, name); return success and result end 2 | local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") 3 | 4 | function test() 5 | local t = table.create(250001, 0) 6 | 7 | for i=1,250000 do 8 | t[i] = i 9 | end 10 | 11 | local t2 = table.create(250001, 100) 12 | 13 | local ts0 = os.clock() 14 | table.move(t, 1, 250000, 1, t2) 15 | local ts1 = os.clock() 16 | 17 | for i=1,250000-1 do 18 | assert(t2[i] == i) 19 | end 20 | 21 | return ts1-ts0 22 | end 23 | 24 | bench.runCode(test, "TableMove: table.create") 25 | -------------------------------------------------------------------------------- /bench/micro_tests/test_TableRemoval_table_remove.lua: -------------------------------------------------------------------------------- 1 | local function prequire(name) local success, result = pcall(require, name); return success and result end 2 | local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") 3 | 4 | function test() 5 | 6 | local ts0 = os.clock() 7 | 8 | local iterations = 25000 9 | 10 | local t = table.create(iterations, 100) 11 | 12 | for j=1,100 do 13 | table.remove(t, 1) 14 | end 15 | 16 | assert(#t == (iterations - 100)) 17 | 18 | local ts1 = os.clock() 19 | 20 | return ts1-ts0 21 | end 22 | 23 | bench.runCode(test, "TableRemoval: table.remove") 24 | -------------------------------------------------------------------------------- /bench/micro_tests/test_TableSort.lua: -------------------------------------------------------------------------------- 1 | local function prequire(name) local success, result = pcall(require, name); return success and result end 2 | local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") 3 | 4 | local arr_months = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"} 5 | 6 | local arr_num = {} 7 | for i=1,100 do table.insert(arr_num, math.sin(i)) end 8 | 9 | local arr_numk = {} 10 | for i=1,10000 do table.insert(arr_numk, math.sin(i)) end 11 | 12 | function test(arr) 13 | local t = table.create(#arr) 14 | 15 | for i=1,1e6/#arr do 16 | table.move(arr, 1, #arr, 1, t) 17 | table.sort(t) 18 | end 19 | end 20 | 21 | bench.runCode(function() test(arr_months) end, "table.sort: 12 strings") 22 | bench.runCode(function() test(arr_num) end, "table.sort: 100 numbers") 23 | bench.runCode(function() test(arr_numk) end, "table.sort: 10k numbers") 24 | -------------------------------------------------------------------------------- /bench/micro_tests/test_ToNumberString.lua: -------------------------------------------------------------------------------- 1 | local function prequire(name) local success, result = pcall(require, name); return success and result end 2 | local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") 3 | 4 | bench.runCode(function() 5 | for j=1,1e6 do 6 | tonumber("42") 7 | tonumber(42) 8 | end 9 | end, "tonumber") 10 | 11 | bench.runCode(function() 12 | for j=1,1e6 do 13 | tostring(nil) 14 | tostring("test") 15 | tostring(42) 16 | end 17 | end, "tostring") 18 | 19 | bench.runCode(function() 20 | for j=1,1e6 do 21 | tostring(j) 22 | end 23 | end, "tostring-gc") 24 | -------------------------------------------------------------------------------- /bench/micro_tests/test_UpvalueCapture.lua: -------------------------------------------------------------------------------- 1 | local function prequire(name) local success, result = pcall(require, name); return success and result end 2 | local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") 3 | 4 | function test() 5 | 6 | local tab = {} 7 | 8 | local ts0 = os.clock() 9 | 10 | for i=1, 1_000_000 do 11 | local j = i + 1 12 | tab[i] = function() return i,j end 13 | end 14 | 15 | local ts1 = os.clock() 16 | 17 | return ts1-ts0 18 | end 19 | 20 | bench.runCode(test, "UpvalueCapture") -------------------------------------------------------------------------------- /bench/micro_tests/test_VariadicSelect.lua: -------------------------------------------------------------------------------- 1 | local function prequire(name) local success, result = pcall(require, name); return success and result end 2 | local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") 3 | 4 | function test() 5 | 6 | function sum(...) 7 | local res = 0 8 | local length = select("#", ...) 9 | for i = 1, length do 10 | local item = select(i, ...) 11 | res += item 12 | end 13 | return res 14 | end 15 | 16 | local ts0 = os.clock() 17 | 18 | for i=1, 100_000 do 19 | sum(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) 20 | end 21 | 22 | local ts1 = os.clock() 23 | 24 | return ts1-ts0 25 | end 26 | 27 | bench.runCode(test, "VariadicSelect") 28 | -------------------------------------------------------------------------------- /bench/micro_tests/test_string_lib.lua: -------------------------------------------------------------------------------- 1 | local function prequire(name) local success, result = pcall(require, name); return success and result end 2 | local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") 3 | 4 | bench.runCode(function() 5 | local src = string.rep("abcdefghijklmnopqrstuvwxyz", 100) 6 | local str = "" 7 | for i=1,1000 do 8 | str = string.upper(src) 9 | str = string.reverse(str) 10 | str = string.lower(str) 11 | end 12 | assert(#str) 13 | end, "string: reverse/upper/lower (large)") 14 | 15 | bench.runCode(function() 16 | local str = "" 17 | for i=1,100000 do 18 | src = "abcdefghijklmnopqrstuvwxyz" .. i 19 | str = string.upper(src) 20 | str = string.reverse(str) 21 | str = string.lower(str) 22 | end 23 | assert(#str) 24 | end, "string: reverse/upper/lower (unique)") 25 | 26 | bench.runCode(function() 27 | local str = "" 28 | for i=1,1000000 do 29 | str = string.rep("_", 19) 30 | end 31 | assert(#str) 32 | end, "string: rep (small)") 33 | 34 | bench.runCode(function() 35 | local str = "" 36 | for i=1,100 do 37 | str = string.rep("abcd", 100000) 38 | end 39 | assert(#str) 40 | end, "string: rep (large)") 41 | -------------------------------------------------------------------------------- /bench/micro_tests/test_table_concat.lua: -------------------------------------------------------------------------------- 1 | local function prequire(name) local success, result = pcall(require, name); return success and result end 2 | local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") 3 | 4 | bench.runCode(function() 5 | for outer=1,28,3 do 6 | for inner=1,28,3 do 7 | local t2 = table.create(20, string.rep("n", outer)) 8 | local str = "" 9 | for i=1,500 do 10 | str = table.concat(t2, string.rep("!", inner)) 11 | end 12 | assert(#str) 13 | end 14 | end 15 | end, "table: concat (small)") 16 | 17 | bench.runCode(function() 18 | for outer=1,21,3 do 19 | for inner=1,21,3 do 20 | local t2 = table.create(200, string.rep("n", outer)) 21 | local str = "" 22 | for i=1,100 do 23 | str = table.concat(t2, string.rep("!", inner)) 24 | end 25 | assert(#str) 26 | end 27 | end 28 | end, "table: concat (big)") 29 | -------------------------------------------------------------------------------- /bench/micro_tests/test_vector_lib.lua: -------------------------------------------------------------------------------- 1 | local function prequire(name) local success, result = pcall(require, name); return success and result end 2 | local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") 3 | 4 | bench.runCode(function() 5 | for i=1,1000000 do 6 | vector.create(i, 2, 3) 7 | vector.create(i, 2, 3) 8 | vector.create(i, 2, 3) 9 | vector.create(i, 2, 3) 10 | vector.create(i, 2, 3) 11 | end 12 | end, "vector: create") 13 | 14 | -- TODO: add more tests -------------------------------------------------------------------------------- /bench/other/boatbomber-HashLib/HashLib.spec.lua: -------------------------------------------------------------------------------- 1 | local function describe(phrase, callback) end 2 | local function it(phrase, callback) end 3 | local function expect(value) end 4 | 5 | return function() 6 | local HashLib = require(script.Parent) 7 | local sha256 = HashLib.sha256 8 | 9 | describe("HashLib.sha256", function() 10 | it("should properly encode strings", function() 11 | expect(sha256("abc").to.equal("ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad")) 12 | expect( 13 | sha256("The quick brown fox jumps over the lazy dog").to.equal( 14 | "d7a8fbb307d7809469ca9abcb0082e4f8d5651e46d3cdb762d02d0bf37c9e592" 15 | ) 16 | ) 17 | expect(sha256("123456").to.equal("8d969eef6ecad3c29a3a629280e686cf0c3f5d5a86aff3ca12020c923adc6c92")) 18 | end) 19 | 20 | it("should create a private closure that works", function() 21 | local AppendNextChunk = sha256() 22 | AppendNextChunk("The quick brown fox") 23 | AppendNextChunk(" jumps ") 24 | AppendNextChunk("") -- chunk may be an empty string 25 | AppendNextChunk("over the lazy dog") 26 | expect(AppendNextChunk()).to.equal("d7a8fbb307d7809469ca9abcb0082e4f8d5651e46d3cdb762d02d0bf37c9e592") 27 | end) 28 | 29 | it("should allow the private closure to work if called twice", function() 30 | local AppendNextChunk = sha256() 31 | AppendNextChunk("The quick brown fox") 32 | AppendNextChunk(" jumps ") 33 | AppendNextChunk("") -- chunk may be an empty string 34 | AppendNextChunk("over the lazy dog") 35 | AppendNextChunk() 36 | expect(AppendNextChunk()).to.equal("d7a8fbb307d7809469ca9abcb0082e4f8d5651e46d3cdb762d02d0bf37c9e592") 37 | end) 38 | end) 39 | end 40 | -------------------------------------------------------------------------------- /bench/other/boatbomber-HashLib/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 boatbomber 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 | -------------------------------------------------------------------------------- /bench/tests/matrixmult.lua: -------------------------------------------------------------------------------- 1 | local function prequire(name) local success, result = pcall(require, name); return success and result end 2 | local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") 3 | 4 | local function mmul(matrix1, matrix2) 5 | local shapeRows = #matrix1 6 | local shapeColumns = #matrix2[1] 7 | local result = table.create(shapeRows) 8 | for i = 1, shapeRows do 9 | result[i] = table.create(shapeColumns) 10 | for j = 1, shapeColumns do 11 | local sum = 0 12 | for k = 1, shapeColumns do 13 | sum = sum + matrix1[i][k] * matrix2[k][j] 14 | end 15 | result[i][j] = sum 16 | end 17 | end 18 | return result 19 | end 20 | 21 | function test() 22 | local n = 100 23 | 24 | local mat = table.create(n) 25 | for i = 1, n do 26 | local t = table.create(n) 27 | for k = 1, n do 28 | t[k] = math.random() 29 | end 30 | mat[i] = t 31 | end 32 | 33 | local startTime = os.clock() 34 | 35 | local result = mmul(mat, mat) 36 | 37 | return os.clock() - startTime 38 | end 39 | 40 | bench.runCode(test, "matrixmult") 41 | -------------------------------------------------------------------------------- /bench/tests/pcmmix.lua: -------------------------------------------------------------------------------- 1 | local function prequire(name) local success, result = pcall(require, name); return success and result end 2 | local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") 3 | 4 | local samples = 100_000 5 | 6 | -- create two 16-bit stereo pcm audio buffers 7 | local ch1 = buffer.create(samples * 2 * 2) 8 | local ch2 = buffer.create(samples * 2 * 2) 9 | 10 | -- just init with random data 11 | for i = 0, samples * 2 - 1 do 12 | buffer.writei16(ch1, i * 2, math.random(-32768, 32767)) 13 | buffer.writei16(ch2, i * 2, math.random(-32768, 32767)) 14 | end 15 | 16 | function test() 17 | local mix = buffer.create(samples * 2 * 2) 18 | 19 | for i = 0, samples - 1 do 20 | local s1l = buffer.readi16(ch1, i * 4) 21 | local s1r = buffer.readi16(ch1, i * 4 + 2) 22 | 23 | local s2l = buffer.readi16(ch2, i * 4) 24 | local s2r = buffer.readi16(ch2, i * 4 + 2) 25 | 26 | local combinedl = s1l + s2l - s1l * s2l / 32768 27 | local combinedr = s1r + s2r - s1r * s2r / 32768 28 | 29 | buffer.writei16(mix, i * 4, combinedl) 30 | buffer.writei16(mix, i * 4 + 2, combinedr) 31 | end 32 | end 33 | 34 | bench.runCode(test, "pcmmix") 35 | -------------------------------------------------------------------------------- /bench/tests/sieve.lua: -------------------------------------------------------------------------------- 1 | local function prequire(name) local success, result = pcall(require, name); return success and result end 2 | local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") 3 | 4 | function test() 5 | 6 | -- the sieve of of Eratosthenes programmed with coroutines 7 | -- typical usage: lua -e N=1000 sieve.lua | column 8 | 9 | -- generate all the numbers from 2 to n 10 | function gen (n) 11 | return coroutine.wrap(function () 12 | for i=2,n do coroutine.yield(i) end 13 | end) 14 | end 15 | 16 | -- filter the numbers generated by `g', removing multiples of `p' 17 | function filter (p, g) 18 | return coroutine.wrap(function () 19 | while 1 do 20 | local n = g() 21 | if n == nil then return end 22 | if n % p ~= 0 then coroutine.yield(n) end 23 | end 24 | end) 25 | end 26 | 27 | local ts0 = os.clock() 28 | 29 | for loops=1,100 do 30 | N = 1000 31 | x = gen(N) -- generate primes up to N 32 | while 1 do 33 | local n = x() -- pick a number until done 34 | if n == nil then break end 35 | -- print(n) -- must be a prime number 36 | x = filter(n, x) -- now remove its multiples 37 | end 38 | end 39 | 40 | local ts1 = os.clock() 41 | 42 | return ts1-ts0 43 | end 44 | 45 | bench.runCode(test, "sieve") -------------------------------------------------------------------------------- /bench/tests/sunspider/controlflow-recursive.lua: -------------------------------------------------------------------------------- 1 | --[[ 2 | The Great Computer Language Shootout 3 | http://shootout.alioth.debian.org/ 4 | contributed by Isaac Gouy 5 | ]] 6 | local function prequire(name) local success, result = pcall(require, name); return success and result end 7 | local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../../bench_support") 8 | 9 | function test() 10 | 11 | local function ack(m,n) 12 | if (m==0) then return n+1; end 13 | if (n==0) then return ack(m-1,1); end 14 | return ack(m-1, ack(m,n-1) ); 15 | end 16 | 17 | local function fib(n) 18 | if (n < 2) then return 1; end 19 | return fib(n-2) + fib(n-1); 20 | end 21 | 22 | local function tak(x,y,z) 23 | if (y >= x) then return z; end 24 | return tak(tak(x-1,y,z), tak(y-1,z,x), tak(z-1,x,y)); 25 | end 26 | 27 | local result = 0; 28 | 29 | for i = 3,5 do 30 | result = result + ack(3,i); 31 | result = result + fib(17+i); 32 | result = result + tak(3*i+3,2*i+2,i+1); 33 | end 34 | 35 | local expected = 57775; 36 | 37 | if (result ~= expected) then 38 | assert(false, "ERROR: bad result: expected " .. expected .. " but got " .. result); 39 | end 40 | 41 | end 42 | 43 | bench.runCode(test, "controlflow-recursive") 44 | -------------------------------------------------------------------------------- /bench/tests/sunspider/math-partial-sums.lua: -------------------------------------------------------------------------------- 1 | --[[ 2 | The Great Computer Language Shootout 3 | http://shootout.alioth.debian.org/ 4 | contributed by Isaac Gouy 5 | ]] 6 | local function prequire(name) local success, result = pcall(require, name); return success and result end 7 | local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../../bench_support") 8 | 9 | function test() 10 | 11 | local function partial(n) 12 | local a1, a2, a3, a4, a5, a6, a7, a8, a9 = 0, 0, 0, 0, 0, 0, 0, 0, 0; 13 | local twothirds = 2.0/3.0; 14 | local alt = -1.0; 15 | local k2, k3, sk, ck = 0, 0, 0, 0; 16 | 17 | for k = 1,n do 18 | k2 = k*k; 19 | k3 = k2*k; 20 | sk = math.sin(k); 21 | ck = math.cos(k); 22 | alt = -alt; 23 | 24 | a1 = a1 + math.pow(twothirds,k-1); 25 | a2 = a2 + math.pow(k,-0.5); 26 | a3 = a3 + 1.0/(k*(k+1.0)); 27 | a4 = a4 + 1.0/(k3 * sk*sk); 28 | a5 = a5 + 1.0/(k3 * ck*ck); 29 | a6 = a6 + 1.0/k; 30 | a7 = a7 + 1.0/k2; 31 | a8 = a8 + alt/k; 32 | a9 = a9 + alt/(2*k -1); 33 | end 34 | 35 | return a6 + a7 + a8 + a9; 36 | end 37 | 38 | local total = 0; 39 | local i = 1024 40 | 41 | while i <= 16384 do 42 | total = total + partial(i); 43 | i = i * 2 44 | end 45 | 46 | local expected = 60.08994194659945; 47 | 48 | if (total ~= expected) then 49 | assert(false, "ERROR: bad result: expected " .. expected .. " but got " .. total); 50 | end 51 | 52 | end 53 | 54 | bench.runCode(test, "math-partial-sums") 55 | -------------------------------------------------------------------------------- /bench/tests/vector-math.lua: -------------------------------------------------------------------------------- 1 | local function prequire(name) local success, result = pcall(require, name); if success then return result end return nil end 2 | local bench = script and require(script.Parent.bench_support) or prequire("bench_support") or require("../bench_support") 3 | 4 | function fma(a: vector, b: vector, c: vector) 5 | return a * b + c 6 | end 7 | 8 | function approx(a: vector): vector 9 | local r = vector.create(1, 1, 1) 10 | local aa = a 11 | r += aa * 0.123 12 | aa *= a 13 | r += aa * 0.123 14 | aa *= a 15 | r += aa * 0.123 16 | aa *= a 17 | r += aa * 0.123 18 | aa *= a 19 | r += aa * 0.123 20 | aa *= a 21 | r += aa * 0.123 22 | return r 23 | end 24 | 25 | function test() 26 | local A = vector.create(1, 2, 3) 27 | local B = vector.create(4, 5, 6) 28 | local C = vector.create(7, 8, 9) 29 | local fma = fma 30 | local approx = approx 31 | 32 | for i=1,100000 do 33 | fma(A, B, C) 34 | 35 | approx(A) 36 | end 37 | end 38 | 39 | bench.runCode(test, "vector-math") 40 | -------------------------------------------------------------------------------- /extern/.clang-format: -------------------------------------------------------------------------------- 1 | DisableFormat: true 2 | SortIncludes: false 3 | -------------------------------------------------------------------------------- /extern/isocline/.gitignore: -------------------------------------------------------------------------------- 1 | out/ 2 | build/ 3 | dist/ 4 | doc/html/ 5 | .vs/ 6 | .vscode/ 7 | .stack-work/ 8 | .DS_Store 9 | *.user 10 | *.exe 11 | *.hi 12 | *.o 13 | *_stub.h 14 | *.lock 15 | history.txt 16 | isocline.debug.txt -------------------------------------------------------------------------------- /extern/isocline/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Daan Leijen 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 | -------------------------------------------------------------------------------- /extern/isocline/src/bbcode.h: -------------------------------------------------------------------------------- 1 | /* ---------------------------------------------------------------------------- 2 | Copyright (c) 2021, Daan Leijen 3 | This is free software; you can redistribute it and/or modify it 4 | under the terms of the MIT License. A copy of the license can be 5 | found in the "LICENSE" file at the root of this distribution. 6 | -----------------------------------------------------------------------------*/ 7 | #pragma once 8 | #ifndef IC_BBCODE_H 9 | #define IC_BBCODE_H 10 | 11 | #include 12 | #include "common.h" 13 | #include "term.h" 14 | 15 | struct bbcode_s; 16 | typedef struct bbcode_s bbcode_t; 17 | 18 | ic_private bbcode_t* bbcode_new( alloc_t* mem, term_t* term ); 19 | ic_private void bbcode_free( bbcode_t* bb ); 20 | 21 | ic_private void bbcode_style_add( bbcode_t* bb, const char* style_name, attr_t attr ); 22 | ic_private void bbcode_style_def( bbcode_t* bb, const char* style_name, const char* s ); 23 | ic_private void bbcode_style_open( bbcode_t* bb, const char* fmt ); 24 | ic_private void bbcode_style_close( bbcode_t* bb, const char* fmt ); 25 | ic_private attr_t bbcode_style( bbcode_t* bb, const char* style_name ); 26 | 27 | ic_private void bbcode_print( bbcode_t* bb, const char* s ); 28 | ic_private void bbcode_println( bbcode_t* bb, const char* s ); 29 | ic_private void bbcode_printf( bbcode_t* bb, const char* fmt, ... ); 30 | ic_private void bbcode_vprintf( bbcode_t* bb, const char* fmt, va_list args ); 31 | 32 | ic_private ssize_t bbcode_column_width( bbcode_t* bb, const char* s ); 33 | 34 | // allows `attr_out == NULL`. 35 | ic_private void bbcode_append( bbcode_t* bb, const char* s, stringbuf_t* out, attrbuf_t* attr_out ); 36 | 37 | #endif // IC_BBCODE_H 38 | -------------------------------------------------------------------------------- /extern/isocline/src/highlight.h: -------------------------------------------------------------------------------- 1 | /* ---------------------------------------------------------------------------- 2 | Copyright (c) 2021, Daan Leijen 3 | This is free software; you can redistribute it and/or modify it 4 | under the terms of the MIT License. A copy of the license can be 5 | found in the "LICENSE" file at the root of this distribution. 6 | -----------------------------------------------------------------------------*/ 7 | #pragma once 8 | #ifndef IC_HIGHLIGHT_H 9 | #define IC_HIGHLIGHT_H 10 | 11 | #include "common.h" 12 | #include "attr.h" 13 | #include "term.h" 14 | #include "bbcode.h" 15 | 16 | //------------------------------------------------------------- 17 | // Syntax highlighting 18 | //------------------------------------------------------------- 19 | 20 | ic_private void highlight( alloc_t* mem, bbcode_t* bb, const char* s, attrbuf_t* attrs, ic_highlight_fun_t* highlighter, void* arg ); 21 | ic_private void highlight_match_braces(const char* s, attrbuf_t* attrs, ssize_t cursor_pos, const char* braces, attr_t match_attr, attr_t error_attr); 22 | ic_private ssize_t find_matching_brace(const char* s, ssize_t cursor_pos, const char* braces, bool* is_balanced); 23 | 24 | #endif // IC_HIGHLIGHT_H 25 | -------------------------------------------------------------------------------- /extern/isocline/src/undo.h: -------------------------------------------------------------------------------- 1 | /* ---------------------------------------------------------------------------- 2 | Copyright (c) 2021, Daan Leijen 3 | This is free software; you can redistribute it and/or modify it 4 | under the terms of the MIT License. A copy of the license can be 5 | found in the "LICENSE" file at the root of this distribution. 6 | -----------------------------------------------------------------------------*/ 7 | #pragma once 8 | #ifndef IC_UNDO_H 9 | #define IC_UNDO_H 10 | 11 | #include "common.h" 12 | 13 | //------------------------------------------------------------- 14 | // Edit state 15 | //------------------------------------------------------------- 16 | struct editstate_s; 17 | typedef struct editstate_s editstate_t; 18 | 19 | ic_private void editstate_init( editstate_t** es ); 20 | ic_private void editstate_done( alloc_t* mem, editstate_t** es ); 21 | ic_private void editstate_capture( alloc_t* mem, editstate_t** es, const char* input, ssize_t pos); 22 | ic_private bool editstate_restore( alloc_t* mem, editstate_t** es, const char** input, ssize_t* pos ); // caller needs to free input 23 | 24 | #endif // IC_UNDO_H 25 | -------------------------------------------------------------------------------- /fuzz/basic.luau: -------------------------------------------------------------------------------- 1 | local function test(t) 2 | for k,v in pairs(t) do 3 | print(k,v) 4 | end 5 | end 6 | 7 | test({a = 1}) 8 | -------------------------------------------------------------------------------- /fuzz/compiler.cpp: -------------------------------------------------------------------------------- 1 | // This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | #include 3 | #include "Luau/Compiler.h" 4 | #include "Luau/Common.h" 5 | 6 | extern "C" int LLVMFuzzerTestOneInput(const uint8_t* Data, size_t Size) 7 | { 8 | Luau::compile(std::string(reinterpret_cast(Data), Size)); 9 | return 0; 10 | } 11 | -------------------------------------------------------------------------------- /fuzz/format.cpp: -------------------------------------------------------------------------------- 1 | // This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | #include "Luau/Common.h" 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | namespace Luau 9 | { 10 | void fuzzFormatString(const char* data, size_t size); 11 | } // namespace Luau 12 | 13 | extern "C" int LLVMFuzzerTestOneInput(const uint8_t* Data, size_t Size) 14 | { 15 | // copy data to heap to make sure ASAN can catch out of bounds access 16 | std::vector str(Data, Data + Size); 17 | 18 | Luau::fuzzFormatString(str.data(), str.size()); 19 | 20 | return 0; 21 | } 22 | -------------------------------------------------------------------------------- /fuzz/libprotobuf-mutator-patch.patch: -------------------------------------------------------------------------------- 1 | diff --git a/CMakeLists.txt b/CMakeLists.txt 2 | index 4805c82..9f0df5c 100644 3 | --- a/CMakeLists.txt 4 | +++ b/CMakeLists.txt 5 | @@ -149,7 +149,6 @@ add_subdirectory(src) 6 | 7 | if (NOT "${LIB_PROTO_MUTATOR_FUZZER_LIBRARIES}" STREQUAL "" OR 8 | NOT "${FUZZING_FLAGS}" STREQUAL "") 9 | - add_subdirectory(examples EXCLUDE_FROM_ALL) 10 | endif() 11 | 12 | install(EXPORT libprotobuf-mutatorTargets FILE libprotobuf-mutatorTargets.cmake 13 | -------------------------------------------------------------------------------- /fuzz/linter.cpp: -------------------------------------------------------------------------------- 1 | // This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | #include 3 | 4 | #include "Luau/BuiltinDefinitions.h" 5 | #include "Luau/Common.h" 6 | #include "Luau/Frontend.h" 7 | #include "Luau/Linter.h" 8 | #include "Luau/ModuleResolver.h" 9 | #include "Luau/Parser.h" 10 | 11 | extern "C" int LLVMFuzzerTestOneInput(const uint8_t* Data, size_t Size) 12 | { 13 | Luau::ParseOptions options; 14 | 15 | Luau::Allocator allocator; 16 | Luau::AstNameTable names(allocator); 17 | 18 | Luau::ParseResult parseResult = Luau::Parser::parse(reinterpret_cast(Data), Size, names, allocator, options); 19 | 20 | // "static" here is to accelerate fuzzing process by only creating and populating the type environment once 21 | static Luau::NullFileResolver fileResolver; 22 | static Luau::NullConfigResolver configResolver; 23 | static Luau::Frontend frontend{&fileResolver, &configResolver}; 24 | static int once = (Luau::registerBuiltinGlobals(frontend, frontend.globals, false), 1); 25 | (void)once; 26 | static int once2 = (Luau::freeze(frontend.globals.globalTypes), 1); 27 | (void)once2; 28 | 29 | if (parseResult.errors.empty()) 30 | { 31 | Luau::TypeChecker typeck(frontend.globals.globalScope, &frontend.moduleResolver, frontend.builtinTypes, &frontend.iceHandler); 32 | 33 | Luau::LintOptions lintOptions; 34 | lintOptions.warningMask = ~0ull; 35 | 36 | Luau::lint(parseResult.root, names, typeck.globalScope, nullptr, {}, lintOptions); 37 | } 38 | 39 | return 0; 40 | } 41 | -------------------------------------------------------------------------------- /fuzz/number.cpp: -------------------------------------------------------------------------------- 1 | // This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | #include "Luau/Common.h" 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #define LUAI_MAXNUM2STR 48 10 | 11 | char* luai_num2str(char* buf, double n); 12 | 13 | extern "C" int LLVMFuzzerTestOneInput(const uint8_t* Data, size_t Size) 14 | { 15 | if (Size < 8) 16 | return 0; 17 | 18 | double num; 19 | memcpy(&num, Data, 8); 20 | 21 | char buf[LUAI_MAXNUM2STR]; 22 | char* end = luai_num2str(buf, num); 23 | LUAU_ASSERT(end < buf + sizeof(buf)); 24 | 25 | *end = 0; 26 | 27 | double rec = strtod(buf, nullptr); 28 | 29 | LUAU_ASSERT(rec == num || (rec != rec && num != num)); 30 | return 0; 31 | } 32 | -------------------------------------------------------------------------------- /fuzz/parser.cpp: -------------------------------------------------------------------------------- 1 | // This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | #include 3 | #include "Luau/Parser.h" 4 | #include "Luau/Common.h" 5 | 6 | extern "C" int LLVMFuzzerTestOneInput(const uint8_t* Data, size_t Size) 7 | { 8 | Luau::ParseOptions options; 9 | 10 | Luau::Allocator allocator; 11 | Luau::AstNameTable names(allocator); 12 | 13 | Luau::Parser::parse(reinterpret_cast(Data), Size, names, allocator, options); 14 | return 0; 15 | } 16 | -------------------------------------------------------------------------------- /fuzz/prototest.cpp: -------------------------------------------------------------------------------- 1 | // This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | #include "src/libfuzzer/libfuzzer_macro.h" 3 | #include "luau.pb.h" 4 | 5 | std::vector protoprint(const luau::ModuleSet& stat, bool types); 6 | 7 | DEFINE_PROTO_FUZZER(const luau::ModuleSet& message) 8 | { 9 | std::vector sources = protoprint(message, true); 10 | 11 | for (size_t i = 0; i < sources.size(); i++) 12 | { 13 | printf("Module 'l%d':\n", int(i)); 14 | printf("%s\n", sources[i].c_str()); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /fuzz/syntax.dict: -------------------------------------------------------------------------------- 1 | "and" 2 | "break" 3 | "do" 4 | "else" 5 | "elseif" 6 | "end" 7 | "false" 8 | "for" 9 | "function" 10 | "if" 11 | "in" 12 | "local" 13 | "nil" 14 | "not" 15 | "or" 16 | "repeat" 17 | "return" 18 | "then" 19 | "true" 20 | "until" 21 | "while" 22 | -------------------------------------------------------------------------------- /fuzz/transpiler.cpp: -------------------------------------------------------------------------------- 1 | // This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | #include 3 | #include "Luau/Transpiler.h" 4 | #include "Luau/Common.h" 5 | 6 | extern "C" int LLVMFuzzerTestOneInput(const uint8_t* Data, size_t Size) 7 | { 8 | Luau::transpile(std::string_view(reinterpret_cast(Data), Size)); 9 | return 0; 10 | } 11 | -------------------------------------------------------------------------------- /lua_LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright © 1994–2019 Lua.org, PUC-Rio. 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of 4 | this software and associated documentation files (the "Software"), to deal in 5 | the Software without restriction, including without limitation the rights to 6 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 7 | of the Software, and to permit persons to whom the Software is furnished to do 8 | so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | -------------------------------------------------------------------------------- /tests/AstQueryDsl.cpp: -------------------------------------------------------------------------------- 1 | // This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | 3 | #include "AstQueryDsl.h" 4 | 5 | namespace Luau 6 | { 7 | 8 | FindNthOccurenceOf::FindNthOccurenceOf(Nth nth) 9 | : requestedNth(nth) 10 | { 11 | } 12 | 13 | bool FindNthOccurenceOf::checkIt(AstNode* n) 14 | { 15 | if (theNode) 16 | return false; 17 | 18 | if (n->classIndex == requestedNth.classIndex) 19 | { 20 | // Human factor: the requestedNth starts from 1 because of the term `nth`. 21 | if (currentOccurrence + 1 != requestedNth.nth) 22 | ++currentOccurrence; 23 | else 24 | theNode = n; 25 | } 26 | 27 | return !theNode; // once found, returns false and stops traversal 28 | } 29 | 30 | bool FindNthOccurenceOf::visit(AstNode* n) 31 | { 32 | return checkIt(n); 33 | } 34 | 35 | bool FindNthOccurenceOf::visit(AstType* t) 36 | { 37 | return checkIt(t); 38 | } 39 | 40 | bool FindNthOccurenceOf::visit(AstTypePack* t) 41 | { 42 | return checkIt(t); 43 | } 44 | 45 | } // namespace Luau 46 | -------------------------------------------------------------------------------- /tests/ClassFixture.h: -------------------------------------------------------------------------------- 1 | // This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | #pragma once 3 | 4 | #include "Fixture.h" 5 | 6 | namespace Luau 7 | { 8 | 9 | struct ExternTypeFixture : BuiltinsFixture 10 | { 11 | explicit ExternTypeFixture(bool prepareAutocomplete = false); 12 | 13 | TypeId vector2Type; 14 | TypeId vector2InstanceType; 15 | }; 16 | 17 | } // namespace Luau 18 | -------------------------------------------------------------------------------- /tests/ConstraintGeneratorFixture.h: -------------------------------------------------------------------------------- 1 | // This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | #pragma once 3 | 4 | #include "Luau/ConstraintGenerator.h" 5 | #include "Luau/ConstraintSolver.h" 6 | #include "Luau/DcrLogger.h" 7 | #include "Luau/EqSatSimplification.h" 8 | #include "Luau/Module.h" 9 | #include "Luau/TypeArena.h" 10 | 11 | #include "Fixture.h" 12 | #include "ScopedFlags.h" 13 | 14 | namespace Luau 15 | { 16 | 17 | struct ConstraintGeneratorFixture : Fixture 18 | { 19 | TypeArena arena; 20 | ModulePtr mainModule; 21 | DcrLogger logger; 22 | UnifierSharedState sharedState{&ice}; 23 | Normalizer normalizer{&arena, builtinTypes, NotNull{&sharedState}}; 24 | SimplifierPtr simplifier; 25 | TypeCheckLimits limits; 26 | TypeFunctionRuntime typeFunctionRuntime{NotNull{&ice}, NotNull{&limits}}; 27 | 28 | std::unique_ptr dfg; 29 | std::unique_ptr cg; 30 | Scope* rootScope = nullptr; 31 | 32 | std::vector> constraints; 33 | 34 | ScopedFastFlag forceTheFlag; 35 | 36 | ConstraintGeneratorFixture(); 37 | 38 | void generateConstraints(const std::string& code); 39 | void solve(const std::string& code); 40 | }; 41 | 42 | } // namespace Luau 43 | -------------------------------------------------------------------------------- /tests/ConstraintSolver.test.cpp: -------------------------------------------------------------------------------- 1 | // This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | 3 | #include "ConstraintGeneratorFixture.h" 4 | #include "Fixture.h" 5 | #include "doctest.h" 6 | 7 | LUAU_FASTFLAG(LuauSolverV2); 8 | 9 | using namespace Luau; 10 | 11 | static TypeId requireBinding(Scope* scope, const char* name) 12 | { 13 | auto b = linearSearchForBinding(scope, name); 14 | LUAU_ASSERT(b.has_value()); 15 | return *b; 16 | } 17 | 18 | TEST_SUITE_BEGIN("ConstraintSolver"); 19 | 20 | TEST_CASE_FIXTURE(ConstraintGeneratorFixture, "constraint_basics") 21 | { 22 | solve(R"( 23 | local a = 55 24 | local b = a 25 | )"); 26 | 27 | TypeId bType = requireBinding(rootScope, "b"); 28 | 29 | CHECK("number" == toString(bType)); 30 | } 31 | 32 | TEST_CASE_FIXTURE(ConstraintGeneratorFixture, "generic_function") 33 | { 34 | solve(R"( 35 | local function id(a) 36 | return a 37 | end 38 | )"); 39 | 40 | TypeId idType = requireBinding(rootScope, "id"); 41 | 42 | CHECK("(a) -> a" == toString(idType)); 43 | } 44 | 45 | TEST_CASE_FIXTURE(ConstraintGeneratorFixture, "proper_let_generalization") 46 | { 47 | solve(R"( 48 | local function a(c) 49 | local function d(e) 50 | return c 51 | end 52 | 53 | return d 54 | end 55 | 56 | local b = a(5) 57 | )"); 58 | 59 | TypeId idType = requireBinding(rootScope, "b"); 60 | 61 | CHECK("(unknown) -> number" == toString(idType)); 62 | } 63 | 64 | TEST_SUITE_END(); 65 | -------------------------------------------------------------------------------- /tests/DiffAsserts.cpp: -------------------------------------------------------------------------------- 1 | // This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | 3 | #include "DiffAsserts.h" 4 | 5 | #include 6 | 7 | namespace Luau 8 | { 9 | 10 | 11 | std::string toString(const DifferResult& result) 12 | { 13 | if (result.diffError) 14 | return result.diffError->toString(); 15 | else 16 | return ""; 17 | } 18 | 19 | template<> 20 | std::string diff(TypeId l, TypeId r) 21 | { 22 | return toString(diff(l, r)); 23 | } 24 | 25 | template<> 26 | std::string diff(const Type& l, const Type& r) 27 | { 28 | return toString(diff(&l, &r)); 29 | } 30 | 31 | } // namespace Luau 32 | -------------------------------------------------------------------------------- /tests/DiffAsserts.h: -------------------------------------------------------------------------------- 1 | // This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | #pragma once 3 | 4 | #include "Luau/Differ.h" 5 | #include "Luau/TypeFwd.h" 6 | 7 | #include "doctest.h" 8 | 9 | #include 10 | #include 11 | 12 | namespace Luau 13 | { 14 | 15 | std::string toString(const DifferResult& result); 16 | 17 | template 18 | std::string diff(L, R) 19 | { 20 | return ""; 21 | } 22 | 23 | template<> 24 | std::string diff(TypeId l, TypeId r); 25 | 26 | template<> 27 | std::string diff(const Type& l, const Type& r); 28 | 29 | } // namespace Luau 30 | 31 | // Note: the do-while blocks in the macros below is to scope the INFO block to 32 | // only that assertion. 33 | 34 | #define CHECK_EQ_DIFF(l, r) \ 35 | do \ 36 | { \ 37 | INFO("Left and right values were not equal: ", diff(l, r)); \ 38 | CHECK_EQ(l, r); \ 39 | } while (false); 40 | 41 | #define REQUIRE_EQ_DIFF(l, r) \ 42 | do \ 43 | { \ 44 | INFO("Left and right values were not equal: ", diff(l, r)); \ 45 | REQUIRE_EQ(l, r); \ 46 | } while (false); 47 | -------------------------------------------------------------------------------- /tests/EqSat.slice.test.cpp: -------------------------------------------------------------------------------- 1 | // This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | #include 3 | 4 | #include "Luau/Slice.h" 5 | 6 | #include 7 | 8 | using namespace Luau; 9 | 10 | TEST_SUITE_BEGIN("EqSatSlice"); 11 | 12 | TEST_CASE("slice_is_a_view_over_array") 13 | { 14 | std::array a{1, 2, 3, 4, 5, 6, 7, 8}; 15 | 16 | EqSat::Slice slice{a}; 17 | 18 | CHECK(slice.data() == a.data()); 19 | CHECK(slice.size() == a.size()); 20 | 21 | for (size_t i = 0; i < a.size(); ++i) 22 | { 23 | CHECK(slice[i] == a[i]); 24 | CHECK(&slice[i] == &a[i]); 25 | } 26 | } 27 | 28 | TEST_CASE("slice_is_a_view_over_vector") 29 | { 30 | std::vector vector{1, 2, 3, 4, 5, 6, 7, 8}; 31 | 32 | EqSat::Slice slice{vector.data(), vector.size()}; 33 | 34 | CHECK(slice.data() == vector.data()); 35 | CHECK(slice.size() == vector.size()); 36 | 37 | for (size_t i = 0; i < vector.size(); ++i) 38 | { 39 | CHECK(slice[i] == vector[i]); 40 | CHECK(&slice[i] == &vector[i]); 41 | } 42 | } 43 | 44 | TEST_CASE("mutate_via_slice") 45 | { 46 | std::array a{1, 2}; 47 | CHECK(a[0] == 1); 48 | CHECK(a[1] == 2); 49 | 50 | EqSat::Slice slice{a}; 51 | slice[0] = 42; 52 | slice[1] = 37; 53 | 54 | CHECK(a[0] == 42); 55 | CHECK(a[1] == 37); 56 | } 57 | 58 | TEST_SUITE_END(); 59 | -------------------------------------------------------------------------------- /tests/InferPolarity.test.cpp: -------------------------------------------------------------------------------- 1 | // This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | #include "Fixture.h" 3 | 4 | #include "Luau/InferPolarity.h" 5 | #include "Luau/Polarity.h" 6 | #include "Luau/Type.h" 7 | #include "Luau/TypeArena.h" 8 | 9 | using namespace Luau; 10 | 11 | LUAU_FASTFLAG(LuauEagerGeneralization2); 12 | 13 | TEST_SUITE_BEGIN("InferPolarity"); 14 | 15 | TEST_CASE_FIXTURE(Fixture, "T where T = { m: (a) -> T }") 16 | { 17 | ScopedFastFlag sff{FFlag::LuauEagerGeneralization2, true}; 18 | 19 | TypeArena arena; 20 | ScopePtr globalScope = std::make_shared(builtinTypes->anyTypePack); 21 | 22 | TypeId tType = arena.addType(BlockedType{}); 23 | TypeId aType = arena.addType(GenericType{globalScope.get(), "a"}); 24 | 25 | TypeId mType = arena.addType(FunctionType{ 26 | TypeLevel{}, 27 | /* generics */ {aType}, 28 | /* genericPacks */ {}, 29 | /* argPack */ arena.addTypePack({aType}), 30 | /* retPack */ arena.addTypePack({tType}) 31 | }); 32 | 33 | emplaceType( 34 | asMutable(tType), 35 | TableType{ 36 | TableType::Props{{"m", Property::rw(mType)}}, 37 | /* indexer */ std::nullopt, 38 | TypeLevel{}, 39 | globalScope.get(), 40 | TableState::Sealed 41 | } 42 | ); 43 | 44 | inferGenericPolarities(NotNull{&arena}, NotNull{globalScope.get()}, tType); 45 | 46 | const GenericType* aGeneric = get(aType); 47 | REQUIRE(aGeneric); 48 | CHECK(aGeneric->polarity == Polarity::Negative); 49 | } 50 | 51 | TEST_SUITE_END(); 52 | -------------------------------------------------------------------------------- /tests/Instantiation2.test.cpp: -------------------------------------------------------------------------------- 1 | // This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | 3 | #include "Luau/Instantiation2.h" 4 | 5 | #include "Fixture.h" 6 | #include "ClassFixture.h" 7 | #include "Luau/Type.h" 8 | #include "ScopedFlags.h" 9 | 10 | #include "doctest.h" 11 | 12 | using namespace Luau; 13 | 14 | TEST_SUITE_BEGIN("Instantiation2Test"); 15 | 16 | TEST_CASE_FIXTURE(Fixture, "weird_cyclic_instantiation") 17 | { 18 | TypeArena arena; 19 | Scope scope(builtinTypes->anyTypePack); 20 | 21 | TypeId genericT = arena.addType(GenericType{"T"}); 22 | 23 | TypeId idTy = arena.addType(FunctionType{ 24 | /* generics */ {genericT}, 25 | /* genericPacks */ {}, 26 | /* argTypes */ arena.addTypePack({genericT}), 27 | /* retTypes */ arena.addTypePack({genericT}) 28 | }); 29 | 30 | DenseHashMap genericSubstitutions{nullptr}; 31 | DenseHashMap genericPackSubstitutions{nullptr}; 32 | 33 | TypeId freeTy = arena.freshType(builtinTypes, &scope); 34 | FreeType* ft = getMutable(freeTy); 35 | REQUIRE(ft); 36 | ft->lowerBound = idTy; 37 | ft->upperBound = builtinTypes->unknownType; 38 | 39 | genericSubstitutions[genericT] = freeTy; 40 | 41 | CHECK("(T) -> T" == toString(idTy)); 42 | 43 | std::optional res = instantiate2(&arena, std::move(genericSubstitutions), std::move(genericPackSubstitutions), idTy); 44 | 45 | // Substitutions should not mutate the original type! 46 | CHECK("(T) -> T" == toString(idTy)); 47 | 48 | REQUIRE(res); 49 | CHECK("(T) -> T" == toString(*res)); 50 | } 51 | 52 | TEST_SUITE_END(); 53 | -------------------------------------------------------------------------------- /tests/IostreamOptional.h: -------------------------------------------------------------------------------- 1 | // This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | #pragma once 3 | 4 | #include "Luau/DenseHash.h" 5 | #include 6 | #include 7 | 8 | namespace std 9 | { 10 | 11 | inline std::ostream& operator<<(std::ostream& lhs, const std::nullopt_t&) 12 | { 13 | return lhs << "none"; 14 | } 15 | 16 | template 17 | auto operator<<(std::ostream& lhs, const std::optional& t) -> decltype(lhs << *t) // SFINAE to only instantiate << for supported types 18 | { 19 | if (t) 20 | return lhs << *t; 21 | else 22 | return lhs << "none"; 23 | } 24 | 25 | template 26 | auto operator<<(std::ostream& lhs, const std::vector& t) -> decltype(lhs << t[0]) 27 | { 28 | lhs << "{ "; 29 | bool first = true; 30 | for (const T& element : t) 31 | { 32 | if (first) 33 | first = false; 34 | else 35 | lhs << ", "; 36 | 37 | lhs << element; 38 | } 39 | 40 | return lhs << " }"; 41 | } 42 | 43 | template 44 | auto operator<<(std::ostream& lhs, const Luau::DenseHashSet& set) -> decltype(lhs << *set.begin()) 45 | { 46 | lhs << "{ "; 47 | bool first = true; 48 | for (const K& element : set) 49 | { 50 | if (first) 51 | first = false; 52 | else 53 | lhs << ", "; 54 | 55 | lhs << element; 56 | } 57 | 58 | return lhs << " }"; 59 | } 60 | 61 | } // namespace std 62 | -------------------------------------------------------------------------------- /tests/IrRegAllocX64.test.cpp: -------------------------------------------------------------------------------- 1 | // This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | #include "Luau/IrRegAllocX64.h" 3 | 4 | #include "doctest.h" 5 | 6 | using namespace Luau::CodeGen; 7 | using namespace Luau::CodeGen::X64; 8 | 9 | class IrRegAllocX64Fixture 10 | { 11 | public: 12 | IrRegAllocX64Fixture() 13 | : build(/* logText */ true, ABIX64::Windows) 14 | , regs(build, function, nullptr) 15 | { 16 | } 17 | 18 | void checkMatch(std::string expected) 19 | { 20 | build.finalize(); 21 | 22 | CHECK("\n" + build.text == expected); 23 | } 24 | 25 | AssemblyBuilderX64 build; 26 | IrFunction function; 27 | IrRegAllocX64 regs; 28 | }; 29 | 30 | TEST_SUITE_BEGIN("IrRegAllocX64"); 31 | 32 | TEST_CASE_FIXTURE(IrRegAllocX64Fixture, "RelocateFix") 33 | { 34 | IrInst irInst0{IrCmd::LOAD_DOUBLE}; 35 | irInst0.lastUse = 2; 36 | function.instructions.push_back(irInst0); 37 | 38 | IrInst irInst1{IrCmd::LOAD_DOUBLE}; 39 | irInst1.lastUse = 2; 40 | function.instructions.push_back(irInst1); 41 | 42 | function.instructions[0].regX64 = regs.takeReg(rax, 0); 43 | regs.preserve(function.instructions[0]); 44 | 45 | function.instructions[1].regX64 = regs.takeReg(rax, 1); 46 | regs.restore(function.instructions[0], true); 47 | 48 | LUAU_ASSERT(function.instructions[0].regX64 == rax); 49 | LUAU_ASSERT(function.instructions[1].spilled); 50 | 51 | checkMatch(R"( 52 | vmovsd qword ptr [rsp+048h],rax 53 | vmovsd qword ptr [rsp+050h],rax 54 | vmovsd rax,qword ptr [rsp+048h] 55 | )"); 56 | } 57 | 58 | TEST_SUITE_END(); 59 | -------------------------------------------------------------------------------- /tests/RegisterCallbacks.cpp: -------------------------------------------------------------------------------- 1 | // This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | 3 | #include "RegisterCallbacks.h" 4 | 5 | namespace Luau 6 | { 7 | 8 | std::unordered_set& getRegisterCallbacks() 9 | { 10 | static std::unordered_set cbs; 11 | return cbs; 12 | } 13 | 14 | int addTestCallback(RegisterCallback cb) 15 | { 16 | getRegisterCallbacks().insert(cb); 17 | return 0; 18 | } 19 | 20 | } // namespace Luau 21 | -------------------------------------------------------------------------------- /tests/RegisterCallbacks.h: -------------------------------------------------------------------------------- 1 | // This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | #pragma once 3 | 4 | #include 5 | #include 6 | 7 | namespace Luau 8 | { 9 | 10 | using RegisterCallback = void (*)(); 11 | 12 | /// Gets a set of callbacks to run immediately before running tests, intended 13 | /// for registering new tests at runtime. 14 | std::unordered_set& getRegisterCallbacks(); 15 | 16 | /// Adds a new callback to be ran immediately before running tests. 17 | /// 18 | /// @param cb the callback to add. 19 | /// @returns a dummy integer to satisfy a doctest internal contract. 20 | int addTestCallback(RegisterCallback cb); 21 | 22 | } // namespace Luau 23 | -------------------------------------------------------------------------------- /tests/ScopedFlags.h: -------------------------------------------------------------------------------- 1 | // This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | #pragma once 3 | 4 | #include "Luau/Common.h" 5 | 6 | #include 7 | 8 | template 9 | struct [[nodiscard]] ScopedFValue 10 | { 11 | private: 12 | Luau::FValue* value = nullptr; 13 | T oldValue = T(); 14 | 15 | public: 16 | ScopedFValue(Luau::FValue& fvalue, T newValue) 17 | { 18 | value = &fvalue; 19 | oldValue = fvalue.value; 20 | fvalue.value = newValue; 21 | } 22 | 23 | ScopedFValue(const ScopedFValue&) = delete; 24 | ScopedFValue& operator=(const ScopedFValue&) = delete; 25 | 26 | ScopedFValue(ScopedFValue&& rhs) 27 | { 28 | value = rhs.value; 29 | oldValue = rhs.oldValue; 30 | 31 | rhs.value = nullptr; 32 | } 33 | 34 | ScopedFValue& operator=(ScopedFValue&& rhs) 35 | { 36 | value = rhs.value; 37 | oldValue = rhs.oldValue; 38 | 39 | rhs.value = nullptr; 40 | 41 | return *this; 42 | } 43 | 44 | ~ScopedFValue() 45 | { 46 | if (value) 47 | value->value = oldValue; 48 | } 49 | }; 50 | 51 | using ScopedFastFlag = ScopedFValue; 52 | using ScopedFastInt = ScopedFValue; -------------------------------------------------------------------------------- /tests/conformance/apicalls.luau: -------------------------------------------------------------------------------- 1 | -- This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | print('testing function calls through API') 3 | 4 | function add(a, b) 5 | return a + b 6 | end 7 | 8 | local m = { __eq = function(a, b) return a.a == b.a end } 9 | 10 | function create_with_tm(x) 11 | return setmetatable({ a = x }, m) 12 | end 13 | 14 | local gen = 0 15 | function incuv() 16 | gen += 1 17 | return gen 18 | end 19 | 20 | pi = 3.1415926 21 | function getpi() 22 | return pi 23 | end 24 | 25 | function largealloc() 26 | table.create(1000000) 27 | end 28 | 29 | function oops() 30 | return "oops" 31 | end 32 | 33 | return('OK') 34 | -------------------------------------------------------------------------------- /tests/conformance/assert.luau: -------------------------------------------------------------------------------- 1 | -- This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | print("testing asserts") -- someone has to 3 | 4 | if pcall(assert, false) or pcall(function() assert(false) end) then 5 | error('catastrophic assertion failure') -- surely error() can't be broken 6 | end 7 | 8 | function ecall(fn, ...) 9 | local ok, err = pcall(fn, ...) 10 | assert(not ok) 11 | return err:sub(err:find(": ") + 2, #err) 12 | end 13 | 14 | -- zero-ret calls work 15 | assert(1) 16 | assert(true) 17 | 18 | -- returns first arg 19 | assert(assert(1) == 1) 20 | assert(type(assert({})) == 'table') 21 | 22 | -- fails correctly 23 | assert(ecall(function() assert() end) == "missing argument #1") 24 | assert(ecall(function() assert(nil) end) == "assertion failed!") 25 | assert(ecall(function() assert(false) end) == "assertion failed!") 26 | 27 | -- fails with a message 28 | assert(ecall(function() assert(nil, "epic fail") end) == "epic fail") 29 | 30 | -- returns all arguments for multi-arg calls 31 | assert(select('#', assert(1, 2, 3)) == 3) 32 | assert(table.concat(table.pack(assert(1, 2, 3)), "") == "123") 33 | 34 | return('OK') 35 | -------------------------------------------------------------------------------- /tests/conformance/exceptions.luau: -------------------------------------------------------------------------------- 1 | -- This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | print('testing lua_exception') 3 | 4 | -- Verify that no exception is generated 5 | function empty_function() 6 | end 7 | 8 | function pass_number_to_error() 9 | -- Verify the error value of 42 is part of the exception's string. 10 | error(42) 11 | end 12 | 13 | function pass_string_to_error() 14 | -- Verify the error value of "string argument" is part of the exception's string. 15 | error("string argument") 16 | end 17 | 18 | function pass_table_to_error() 19 | -- Pass a table to `error`. A table is used since it is won't be 20 | -- convertable to a string using `lua_tostring`. 21 | error({field="value"}) 22 | end 23 | 24 | function infinite_recursion_error() 25 | -- Generate a stack overflow error 26 | infinite_recursion_error() 27 | end 28 | 29 | function large_allocation_error() 30 | -- Create a table that will require more memory than the test's memory 31 | -- allocator will allow. 32 | table.create(1000000) 33 | end 34 | 35 | return('OK') 36 | -------------------------------------------------------------------------------- /tests/conformance/literals.luau: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luau-lang/luau/92b03384000710fd9e12ad74a211792717af4296/tests/conformance/literals.luau -------------------------------------------------------------------------------- /tests/conformance/native_userdata.luau: -------------------------------------------------------------------------------- 1 | -- This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | print('testing userdata') 3 | 4 | function ecall(fn, ...) 5 | local ok, err = pcall(fn, ...) 6 | assert(not ok) 7 | return err:sub((err:find(": ") or -1) + 2, #err) 8 | end 9 | 10 | local function realmad(a: vec2, b: vec2, c: vec2): vec2 11 | return -c + a * b; 12 | end 13 | 14 | local function dm(s: vec2, t: vec2, u: vec2) 15 | local x = s:Dot(t) 16 | assert(x == 13) 17 | 18 | local t = u:Min(s) 19 | assert(t.X == 5) 20 | assert(t.Y == 4) 21 | end 22 | 23 | local s: vec2 = vec2(5, 4) 24 | local t: vec2 = vec2(1, 2) 25 | local u: vec2 = vec2(10, 20) 26 | 27 | local x: vec2 = realmad(s, t, u) 28 | 29 | assert(x.X == -5) 30 | assert(x.Y == -12) 31 | 32 | dm(s, t, u) 33 | 34 | local function mu(v: vec2) 35 | assert(v.Magnitude == 2) 36 | assert(v.Unit.X == 0) 37 | assert(v.Unit.Y == 1) 38 | end 39 | 40 | mu(vec2(0, 2)) 41 | 42 | return 'OK' 43 | -------------------------------------------------------------------------------- /tests/conformance/ndebug_upvalues.luau: -------------------------------------------------------------------------------- 1 | -- This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | -- This tests that the lua_*upval() APIs work correctly even with debug info disabled 3 | local foo = 5 4 | function clo_test() 5 | -- so `foo` gets captured as an upval 6 | print(foo) 7 | -- yield so we can look at clo_test's upvalues 8 | coroutine.yield() 9 | end 10 | 11 | clo_test() 12 | 13 | return 'OK' 14 | -------------------------------------------------------------------------------- /tests/conformance/pm.luau: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luau-lang/luau/92b03384000710fd9e12ad74a211792717af4296/tests/conformance/pm.luau -------------------------------------------------------------------------------- /tests/conformance/safeenv.luau: -------------------------------------------------------------------------------- 1 | -- This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | print("safeenv reset") 3 | 4 | local function envChangeInMetamethod() 5 | -- declare constant so that at O2 this test doesn't interfere with constant folding which we can't deoptimize 6 | local ten 7 | ten = 10 8 | 9 | local a = setmetatable({}, { 10 | __index = function() 11 | getfenv().math = { abs = function(n) return n*n end } 12 | return 2 13 | end 14 | }) 15 | 16 | local b = a.x 17 | 18 | assert(math.abs(ten) == 100) 19 | end 20 | 21 | envChangeInMetamethod() 22 | 23 | return"OK" 24 | -------------------------------------------------------------------------------- /tests/conformance/sort.luau: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luau-lang/luau/92b03384000710fd9e12ad74a211792717af4296/tests/conformance/sort.luau -------------------------------------------------------------------------------- /tests/conformance/tmerror.luau: -------------------------------------------------------------------------------- 1 | -- This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | -- This file is based on Lua 5.x tests -- https://github.com/lua/lua/tree/master/testes 3 | 4 | -- Generate an error (i.e. throw an exception) inside a tag method which is indirectly 5 | -- called via pcall. 6 | -- This test is meant to detect a regression in handling errors inside a tag method 7 | 8 | local testtable = {} 9 | setmetatable(testtable, { __index = function() error("Error") end }) 10 | 11 | pcall(function() 12 | testtable.missingmethod() 13 | end) 14 | 15 | -- 16 | local testtable2 = {} 17 | setmetatable(testtable2, { __index = function() pcall(function() error("Error") end) end }) 18 | 19 | local m2 = testtable2.missingmethod 20 | 21 | pcall(function() 22 | testtable2.missingmethod() 23 | end) 24 | 25 | -- 26 | local testtable3 = {} 27 | setmetatable(testtable3, { __index = function() pcall(error, "Error") end }) 28 | 29 | local m3 = testtable3.missingmethod 30 | 31 | pcall(function() 32 | testtable3.missingmethod() 33 | end) 34 | 35 | -- 36 | local testtable4 = {} 37 | setmetatable(testtable4, { __index = function() pcall(error) end }) 38 | 39 | local m4 = testtable4.missingmember 40 | 41 | return('OK') 42 | -------------------------------------------------------------------------------- /tests/conformance/types.luau: -------------------------------------------------------------------------------- 1 | -- This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | print "testing builtin types" 3 | 4 | local ignore = 5 | { 6 | -- these are permanently ignored, as they are only exposed in tests 7 | "_G.limitedstack", 8 | "_G.RTTI", 9 | "_G.collectgarbage", 10 | 11 | -- what follows is a set of mismatches that hopefully eventually will go down to 0 12 | "_G.require", -- need to move to Roblox type defs 13 | } 14 | 15 | function verify(real, rtti, path) 16 | if table.find(ignore, path) then 17 | return 18 | end 19 | 20 | if real and rtti then 21 | if type(real) == "table" then 22 | assert(type(rtti) == "table", path .. " is not a table in type information") 23 | 24 | local keys = {} 25 | 26 | for k, v in pairs(real) do 27 | keys[k] = 1 28 | end 29 | 30 | for k, v in pairs(rtti) do 31 | keys[k] = 1 32 | end 33 | 34 | for k, v in pairs(keys) do 35 | if k ~= "_G" then 36 | verify(real[k], rtti[k], path .. '.' .. k) 37 | end 38 | end 39 | else 40 | assert(type(real) == rtti, path .. " has inconsistent types (" .. type(real) .. " vs " .. rtti .. ")") 41 | end 42 | else 43 | if not rtti then 44 | assert(false, path .. " missing from type information") 45 | else 46 | assert(false, path .. " present in type information but absent from VM") 47 | end 48 | end 49 | end 50 | 51 | verify(getmetatable(_G).__index, RTTI, "_G") 52 | 53 | return 'OK' 54 | -------------------------------------------------------------------------------- /tests/conformance/userdata.luau: -------------------------------------------------------------------------------- 1 | -- This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | print('testing userdata') 3 | 4 | -- int64 is a userdata type defined in C++ 5 | 6 | -- equality 7 | assert(int64(1) == int64(1)) 8 | assert(int64(1) ~= int64(2)) 9 | 10 | -- relational 11 | assert(not (int64(1) < int64(1))) 12 | assert(int64(1) < int64(2)) 13 | assert(int64(1) <= int64(1)) 14 | assert(int64(1) <= int64(2)) 15 | 16 | -- arithmetics 17 | assert(-int64(2) == int64(-2)) 18 | 19 | assert(int64(1) + int64(2) == int64(3)) 20 | assert(int64(1) - int64(2) == int64(-1)) 21 | assert(int64(2) * int64(3) == int64(6)) 22 | assert(int64(4) / int64(2) == int64(2)) 23 | assert(int64(4) % int64(3) == int64(1)) 24 | assert(int64(2) ^ int64(3) == int64(8)) 25 | 26 | assert(int64(1) + 2 == int64(3)) 27 | assert(int64(1) - 2 == int64(-1)) 28 | assert(int64(2) * 3 == int64(6)) 29 | assert(int64(4) / 2 == int64(2)) 30 | assert(int64(4) % 3 == int64(1)) 31 | assert(int64(2) ^ 3 == int64(8)) 32 | 33 | -- / and // round in different directions in our test implementation 34 | assert(int64(5) / int64(2) == int64(2)) 35 | assert(int64(5) // int64(2) == int64(2)) 36 | assert(int64(-5) / int64(2) == int64(-2)) 37 | assert(int64(-5) // int64(2) == int64(-3)) 38 | 39 | -- tostring 40 | assert(tostring(int64(2)) == "2") 41 | 42 | -- index/newindex; note, mutable userdatas aren't very idiomatic but we need to test this 43 | do 44 | local v = int64(42) 45 | assert(v.value == 42) 46 | v.value = 4 47 | assert(v.value == 4) 48 | assert(v == int64(4)) 49 | end 50 | 51 | return 'OK' 52 | -------------------------------------------------------------------------------- /tests/require/with_config/.luaurc: -------------------------------------------------------------------------------- 1 | { 2 | "aliases": { 3 | "dep": "./this_should_be_overwritten_by_child_luaurc", 4 | "otherdep": "./src/other_dependency" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /tests/require/with_config/src/.luaurc: -------------------------------------------------------------------------------- 1 | { 2 | "aliases": { 3 | "dep": "./dependency", 4 | "subdir": "./subdirectory" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /tests/require/with_config/src/alias_requirer.luau: -------------------------------------------------------------------------------- 1 | return require("@dep") 2 | -------------------------------------------------------------------------------- /tests/require/with_config/src/dependency.luau: -------------------------------------------------------------------------------- 1 | return {"result from dependency"} 2 | -------------------------------------------------------------------------------- /tests/require/with_config/src/directory_alias_requirer.luau: -------------------------------------------------------------------------------- 1 | return(require("@subdir/subdirectory_dependency")) 2 | -------------------------------------------------------------------------------- /tests/require/with_config/src/other_dependency.luau: -------------------------------------------------------------------------------- 1 | return {"result from other_dependency"} 2 | -------------------------------------------------------------------------------- /tests/require/with_config/src/parent_alias_requirer.luau: -------------------------------------------------------------------------------- 1 | return require("@otherdep") 2 | -------------------------------------------------------------------------------- /tests/require/with_config/src/subdirectory/subdirectory_dependency.luau: -------------------------------------------------------------------------------- 1 | return {"result from subdirectory_dependency"} 2 | -------------------------------------------------------------------------------- /tests/require/with_config/src/submodule/.luaurc: -------------------------------------------------------------------------------- 1 | { 2 | "aliases": { 3 | "dep": "./this_should_not_be_read_by_init_luau", 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /tests/require/with_config/src/submodule/init.luau: -------------------------------------------------------------------------------- 1 | return require("@dep") 2 | -------------------------------------------------------------------------------- /tests/require/without_config/ambiguous/directory/dependency.luau: -------------------------------------------------------------------------------- 1 | return {"result from dependency"} 2 | -------------------------------------------------------------------------------- /tests/require/without_config/ambiguous/directory/dependency/init.luau: -------------------------------------------------------------------------------- 1 | return {"result from dependency"} 2 | -------------------------------------------------------------------------------- /tests/require/without_config/ambiguous/file/dependency.lua: -------------------------------------------------------------------------------- 1 | return {"result from dependency"} 2 | -------------------------------------------------------------------------------- /tests/require/without_config/ambiguous/file/dependency.luau: -------------------------------------------------------------------------------- 1 | return {"result from dependency"} 2 | -------------------------------------------------------------------------------- /tests/require/without_config/ambiguous_directory_requirer.luau: -------------------------------------------------------------------------------- 1 | local result = require("./ambiguous/directory/dependency") 2 | result[#result+1] = "required into module" 3 | return result 4 | -------------------------------------------------------------------------------- /tests/require/without_config/ambiguous_file_requirer.luau: -------------------------------------------------------------------------------- 1 | local result = require("./ambiguous/file/dependency") 2 | result[#result+1] = "required into module" 3 | return result 4 | -------------------------------------------------------------------------------- /tests/require/without_config/dependency.luau: -------------------------------------------------------------------------------- 1 | return {"result from dependency"} 2 | -------------------------------------------------------------------------------- /tests/require/without_config/lua/init.lua: -------------------------------------------------------------------------------- 1 | return {"result from init.lua"} 2 | -------------------------------------------------------------------------------- /tests/require/without_config/lua_dependency.lua: -------------------------------------------------------------------------------- 1 | return {"result from lua_dependency"} 2 | -------------------------------------------------------------------------------- /tests/require/without_config/luau/init.luau: -------------------------------------------------------------------------------- 1 | return {"result from init.luau"} 2 | -------------------------------------------------------------------------------- /tests/require/without_config/module.luau: -------------------------------------------------------------------------------- 1 | local result = require("./dependency") 2 | result[#result+1] = "required into module" 3 | return result 4 | -------------------------------------------------------------------------------- /tests/require/without_config/nested/init.luau: -------------------------------------------------------------------------------- 1 | local result = require("@self/submodule") 2 | return result 3 | -------------------------------------------------------------------------------- /tests/require/without_config/nested/submodule.luau: -------------------------------------------------------------------------------- 1 | return {"result from submodule"} 2 | -------------------------------------------------------------------------------- /tests/require/without_config/nested_inits/init.luau: -------------------------------------------------------------------------------- 1 | local result = require("@self/init") 2 | return result 3 | -------------------------------------------------------------------------------- /tests/require/without_config/nested_inits/init/init.luau: -------------------------------------------------------------------------------- 1 | return {"result from nested_inits/init"} 2 | -------------------------------------------------------------------------------- /tests/require/without_config/nested_inits_requirer.luau: -------------------------------------------------------------------------------- 1 | local result = require("./nested_inits") 2 | result[#result+1] = "required into module" 3 | return result 4 | -------------------------------------------------------------------------------- /tests/require/without_config/nested_module_requirer.luau: -------------------------------------------------------------------------------- 1 | local result = require("./nested") 2 | result[#result+1] = "required into module" 3 | return result 4 | -------------------------------------------------------------------------------- /tests/require/without_config/proxy_requirer.luau: -------------------------------------------------------------------------------- 1 | local result = proxyrequire("./dependency", "@"..debug.info(1, "s")) 2 | result[#result+1] = "required into proxy_requirer" 3 | return result 4 | -------------------------------------------------------------------------------- /tests/require/without_config/validate_cache.luau: -------------------------------------------------------------------------------- 1 | local result1 = require("./dependency") 2 | local result2 = require("./dependency") 3 | assert(result1 == result2) 4 | return {} -------------------------------------------------------------------------------- /tools/faillist.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/luau-lang/luau/92b03384000710fd9e12ad74a211792717af4296/tools/faillist.txt -------------------------------------------------------------------------------- /tools/fuzz/requirements.txt: -------------------------------------------------------------------------------- 1 | Jinja2==3.1.5 2 | MarkupSafe==2.1.3 3 | -------------------------------------------------------------------------------- /tools/gdb_printers.py: -------------------------------------------------------------------------------- 1 | # This file is part of the Luau programming language and is licensed under MIT License; see LICENSE.txt for details 2 | 3 | class VariantPrinter: 4 | def __init__(self, val): 5 | self.val = val 6 | 7 | def to_string(self): 8 | typeId = int(self.val['typeId']) 9 | type = self.val.type.template_argument(typeId) 10 | value = self.val['storage'].reinterpret_cast(type.pointer()).dereference() 11 | return type.name + " [" + str(value) + "]" 12 | 13 | def match_printer(val): 14 | type = val.type.strip_typedefs() 15 | if type.name and type.name.startswith('Luau::Variant<'): 16 | return VariantPrinter(val) 17 | return None 18 | 19 | gdb.pretty_printers.append(match_printer) 20 | -------------------------------------------------------------------------------- /tools/lldb_formatters.lldb: -------------------------------------------------------------------------------- 1 | type synthetic add -x "^Luau::detail::DenseHashTable<.*>$" -l lldb_formatters.DenseHashTableSyntheticChildrenProvider 2 | type synthetic add -x "^Luau::DenseHashMap<.*>$" -l lldb_formatters.DenseHashMapSyntheticChildrenProvider 3 | type synthetic add -x "^Luau::DenseHashSet<.*>$" -l lldb_formatters.DenseHashSetSyntheticChildrenProvider 4 | 5 | type summary add -x "^Luau::DenseHashMap<.*>$" --summary-string "count = ${var.impl.count}" 6 | type summary add -x "^Luau::DenseHashSet<.*>$" --summary-string "count = ${var.impl.count}" 7 | 8 | type summary add "Luau::Symbol" -F lldb_formatters.luau_symbol_summary 9 | 10 | type synthetic add -x "^Luau::Variant<.+>$" -l lldb_formatters.LuauVariantSyntheticChildrenProvider 11 | type summary add -x "^Luau::Variant<.+>$" -F lldb_formatters.luau_variant_summary 12 | 13 | type synthetic add -x "^Luau::AstArray<.+>$" -l lldb_formatters.AstArraySyntheticChildrenProvider 14 | 15 | type summary add -x "^Luau::NotNull<.+>$" --summary-string "${*var.ptr}" 16 | 17 | type summary add --summary-string "${var.line}:${var.column}" Luau::Position 18 | type summary add --summary-string "${var.begin}-${var.end}" Luau::Location 19 | 20 | type summary add --summary-string "${var.ty} (${var%S})" Luau::TypeId Luau::TypePackId 21 | 22 | type summary add Luau::TypePath::Property -F lldb_formatters.luau_typepath_property_summary 23 | type summary add --summary-string "[${var.index}]" Luau::TypePath::Index 24 | 25 | type summary add -x "^Luau::TryPair<.+>$" --summary-string "(${var.first%T}, ${var.second%T})" 26 | -------------------------------------------------------------------------------- /tools/natvis/Ast.natvis: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | AstArray size={size} 6 | 7 | size 8 | 9 | size 10 | data 11 | 12 | 13 | 14 | 15 | 16 | 17 | size_ 18 | 19 | size_ 20 | storage._Mypair._Myval2._Myfirst + offset 21 | 22 | 23 | 24 | 25 | 26 | {value,na} 27 | 28 | 29 | 30 | {name.value,na} 31 | 32 | 33 | 34 | local {local->name.value,na} 35 | global {global.value,na} 36 | 37 | 38 | 39 | {line}:{column} 40 | 41 | 42 | 43 | {begin}-{end} 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /tools/natvis/Common.natvis: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | count 7 | capacity 8 | 9 | capacity 10 | data 11 | 12 | 13 | 14 | 15 | 16 | 17 | impl 18 | 19 | 20 | 21 | 22 | 23 | impl 24 | 25 | 26 | 27 | 28 | --------------------------------------------------------------------------------