diff --git a/Core/EVIL.Grammar/Parsing/Expressions/Parser.Indexing.cs b/Core/EVIL.Grammar/Parsing/Expressions/Parser.IndexerExpression.cs similarity index 94% rename from Core/EVIL.Grammar/Parsing/Expressions/Parser.Indexing.cs rename to Core/EVIL.Grammar/Parsing/Expressions/Parser.IndexerExpression.cs index 57a38680..9fed47f6 100644 --- a/Core/EVIL.Grammar/Parsing/Expressions/Parser.Indexing.cs +++ b/Core/EVIL.Grammar/Parsing/Expressions/Parser.IndexerExpression.cs @@ -7,7 +7,7 @@ namespace EVIL.Grammar.Parsing { public partial class Parser { - private IndexerExpression Indexing(Expression indexable) + private IndexerExpression IndexerExpression(Expression indexable) { int line, col; Expression indexer; diff --git a/Core/EVIL.Grammar/Parsing/Expressions/Parser.FunctionCall.cs b/Core/EVIL.Grammar/Parsing/Expressions/Parser.InvocationExpression.cs similarity index 89% rename from Core/EVIL.Grammar/Parsing/Expressions/Parser.FunctionCall.cs rename to Core/EVIL.Grammar/Parsing/Expressions/Parser.InvocationExpression.cs index 686fa264..e47e1603 100644 --- a/Core/EVIL.Grammar/Parsing/Expressions/Parser.FunctionCall.cs +++ b/Core/EVIL.Grammar/Parsing/Expressions/Parser.InvocationExpression.cs @@ -6,7 +6,7 @@ namespace EVIL.Grammar.Parsing { public partial class Parser { - private InvocationExpression FunctionCall(Expression callee) + private InvocationExpression InvocationExpression(Expression callee) { var (line, col) = (_lexer.State.Line, _lexer.State.Column); diff --git a/Core/EVIL.Grammar/Parsing/Expressions/Parser.PostfixExpression.cs b/Core/EVIL.Grammar/Parsing/Expressions/Parser.PostfixExpression.cs index 1116435d..7210f060 100644 --- a/Core/EVIL.Grammar/Parsing/Expressions/Parser.PostfixExpression.cs +++ b/Core/EVIL.Grammar/Parsing/Expressions/Parser.PostfixExpression.cs @@ -45,11 +45,11 @@ private Expression PostfixExpression() if (token.Type == TokenType.LParenthesis) { - node = FunctionCall(node); + node = InvocationExpression(node); } else if (token.Type == TokenType.LBracket || token.Type == TokenType.Dot) { - node = Indexing(node); + node = IndexerExpression(node); } else if (token.Type == TokenType.DoubleColon) { diff --git a/Core/EVIL.Grammar/Parsing/Statements/Parser.EachLoop.cs b/Core/EVIL.Grammar/Parsing/Statements/Parser.EachLoop.cs index ec2d0c02..f8f12dc5 100644 --- a/Core/EVIL.Grammar/Parsing/Statements/Parser.EachLoop.cs +++ b/Core/EVIL.Grammar/Parsing/Statements/Parser.EachLoop.cs @@ -14,7 +14,7 @@ private EachStatement EachLoop() if (CurrentToken == Token.Val) { throw new ParserException( - "Each-loop variables must be `rw'.", + "Each-loop variables must be 'rw'.", (_lexer.State.Line, _lexer.State.Column) ); } diff --git a/FrontEnd/EVIL.evil/EvmFrontEnd.cs b/FrontEnd/EVIL.evil/EvmFrontEnd.cs index 44704849..fb9ef84d 100644 --- a/FrontEnd/EVIL.evil/EvmFrontEnd.cs +++ b/FrontEnd/EVIL.evil/EvmFrontEnd.cs @@ -142,6 +142,8 @@ public async Task Run(string[] args) RegisterAllModules(); SetStandardGlobals(scriptPath); + _runtime.RegisterBuiltInFunctions(); + _vm.Scheduler.SetDefaultCrashHandler(CrashHandler); _vm.MainFiber.SetCrashHandler(CrashHandler); _vm.Start(); diff --git a/VirtualMachine/Ceres.Runtime/Ceres.Runtime.csproj b/VirtualMachine/Ceres.Runtime/Ceres.Runtime.csproj index e6a28559..c8753ed9 100644 --- a/VirtualMachine/Ceres.Runtime/Ceres.Runtime.csproj +++ b/VirtualMachine/Ceres.Runtime/Ceres.Runtime.csproj @@ -13,4 +13,11 @@ + + + + + Never + + diff --git a/VirtualMachine/Ceres.Runtime/EvilRuntime.cs b/VirtualMachine/Ceres.Runtime/EvilRuntime.cs index 05bdb1d1..ebd44961 100644 --- a/VirtualMachine/Ceres.Runtime/EvilRuntime.cs +++ b/VirtualMachine/Ceres.Runtime/EvilRuntime.cs @@ -1,28 +1,65 @@ using System; using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection; using Ceres.ExecutionEngine; using Ceres.ExecutionEngine.Collections; +using Ceres.ExecutionEngine.Diagnostics; using Ceres.ExecutionEngine.TypeSystem; using Ceres.Runtime.Extensions; using Ceres.Runtime.Modules; +using Ceres.TranslationEngine; namespace Ceres.Runtime { public sealed class EvilRuntime { private readonly CeresVM _vm; + private readonly Compiler _compiler; private Table Global => _vm.Global; public EvilRuntime(CeresVM vm) { _vm = vm; + _compiler = new Compiler(); + } + + public List RegisterBuiltInFunctions() + { + var scriptNames = Assembly + .GetExecutingAssembly() + .GetManifestResourceNames() + .Where(x => x.StartsWith("Ceres.Runtime.ScriptBuiltins")); + + var list = new List(); + + foreach (var scriptName in scriptNames) + { + using var stream = Assembly + .GetExecutingAssembly() + .GetManifestResourceStream(scriptName)!; + + using var streamReader = new StreamReader(stream); + + var text = streamReader.ReadToEnd(); + var root = _compiler.Compile(text, $"builtin::{scriptName}"); + + foreach (var (name, id) in root.NamedSubChunkLookup) + { + list.Add(root.SubChunks[id]); + _vm.Global.Set(name, root.SubChunks[id]); + } + } + + return list; } public List RegisterBuiltInModules() { var modules = new List(); - + modules.Add(RegisterModule(out _)); modules.Add(RegisterModule(out _)); modules.Add(RegisterModule(out _)); diff --git a/VirtualMachine/Ceres.Runtime/ScriptBuiltins/dofile.vil b/VirtualMachine/Ceres.Runtime/ScriptBuiltins/dofile.vil new file mode 100644 index 00000000..0f4acd50 --- /dev/null +++ b/VirtualMachine/Ceres.Runtime/ScriptBuiltins/dofile.vil @@ -0,0 +1,14 @@ +fn dofile(path) { + if (!fs.file.exists(path)) -> core.error( + "Couldn't find a file at '" + @path + "'." + ); + + val source = fs.file.get_text(path); + val result = evil.compile(source, path); + + if (!result || !result.success) -> core.error( + "Failed to compile the file '" + @path + "': " + @result.message + ); + + ret result.chunk(); +} \ No newline at end of file diff --git a/VirtualMachine/Ceres/TranslationEngine/Compiler.cs b/VirtualMachine/Ceres/TranslationEngine/Compiler.cs index e689adb1..125a0d73 100644 --- a/VirtualMachine/Ceres/TranslationEngine/Compiler.cs +++ b/VirtualMachine/Ceres/TranslationEngine/Compiler.cs @@ -9,6 +9,8 @@ using EVIL.Grammar.AST.Base; using EVIL.Grammar.AST.Constants; using EVIL.Grammar.AST.Miscellaneous; +using EVIL.Grammar.AST.Statements; +using EVIL.Grammar.AST.Statements.TopLevel; using EVIL.Grammar.Parsing; using EVIL.Grammar.Traversal; using EVIL.Lexical; @@ -110,10 +112,10 @@ public Chunk Compile(ProgramNode programNode, string fileName = "") CurrentFileName = fileName; _closedScopes.Clear(); _chunks.Clear(); - + return InRootChunkDo(() => Visit(programNode)); } - + private Chunk InRootChunkDo(Action action) { _rootChunk = new Chunk("!_root_chunk"); @@ -194,13 +196,14 @@ public override void Visit(AstNode node) node = expression.Reduce(); } - base.Visit(node); - - if (_chunks.Any()) + if (_blockDescent > 0 || _chunks.Count == 1) { - var location = LocationStack.Pop(); - Chunk.DebugDatabase.AddDebugRecord(location.Line, Chunk.CodeGenerator.LastOpCodeIP); + Chunk.DebugDatabase.AddDebugRecord(Line, Chunk.CodeGenerator.LastOpCodeIP); } + + base.Visit(node); + + Chunk.DebugDatabase.AddDebugRecord(Line, Chunk.CodeGenerator.LastOpCodeIP); } public void RegisterAttributeProcessor(string attributeName, AttributeProcessor processor)