From 40ef31c1e08cbc3ef30c9f212643eb4e60458f83 Mon Sep 17 00:00:00 2001 From: Ludovic 'Archivist' Lagouardette Date: Tue, 7 Sep 2021 15:04:05 +0200 Subject: [PATCH] Add project files. --- BasicNumber.cs | 60 ++++++++++++++++++++++++++++++ Bytecode.cs | 16 ++++++++ Functions/Multiply.cs | 14 +++++++ Functions/Print.cs | 15 ++++++++ IFunction.cs | 11 ++++++ Library.cs | 29 +++++++++++++++ Parser.cs | 86 +++++++++++++++++++++++++++++++++++++++++++ Program.cs | 18 +++++++++ Runtime.cs | 45 ++++++++++++++++++++++ SuperBASIC.csproj | 14 +++++++ SuperBASIC.sln | 25 +++++++++++++ Test.basic | 2 + 12 files changed, 335 insertions(+) create mode 100644 BasicNumber.cs create mode 100644 Bytecode.cs create mode 100644 Functions/Multiply.cs create mode 100644 Functions/Print.cs create mode 100644 IFunction.cs create mode 100644 Library.cs create mode 100644 Parser.cs create mode 100644 Program.cs create mode 100644 Runtime.cs create mode 100644 SuperBASIC.csproj create mode 100644 SuperBASIC.sln create mode 100644 Test.basic diff --git a/BasicNumber.cs b/BasicNumber.cs new file mode 100644 index 0000000..0ab63c4 --- /dev/null +++ b/BasicNumber.cs @@ -0,0 +1,60 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace SuperBASIC +{ + enum NumberType{ + Ans, + Number, + Operand + }; + + struct BasicNumber + { + internal NumberType type; + + readonly Runtime runtime; + readonly private float number; + readonly private int operand; + + internal BasicNumber(Runtime rt, float v) + { + type = NumberType.Number; + number = v; + operand = 0; + runtime = rt; + } + internal BasicNumber(Runtime rt) + { + type = NumberType.Ans; + number = 0; + operand = 0; + runtime = rt; + } + internal BasicNumber(Runtime rt, int v) + { + type = NumberType.Operand; + number = 0; + operand = v; + runtime = rt; + } + + internal int GetOperand() + { + return operand; + } + + public float GetValue() + { + if (type == NumberType.Number) + { + return number; + } + else + { + return runtime.GetRegister(); + } + } + } +} diff --git a/Bytecode.cs b/Bytecode.cs new file mode 100644 index 0000000..f69a8ba --- /dev/null +++ b/Bytecode.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace SuperBASIC +{ + class Bytecode + { + internal List bytecode; + + internal Bytecode() + { + bytecode = new List(); + } + } +} diff --git a/Functions/Multiply.cs b/Functions/Multiply.cs new file mode 100644 index 0000000..cbfb8e8 --- /dev/null +++ b/Functions/Multiply.cs @@ -0,0 +1,14 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace SuperBASIC.Functions +{ + class Multiply : IFunction + { + float IFunction.Apply(List arguments) + { + return arguments[0].GetValue() * arguments[1].GetValue(); + } + } +} diff --git a/Functions/Print.cs b/Functions/Print.cs new file mode 100644 index 0000000..eb359d7 --- /dev/null +++ b/Functions/Print.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace SuperBASIC.Functions +{ + class Print : IFunction + { + float IFunction.Apply(List arguments) + { + Console.WriteLine(arguments[0].GetValue()); + return 0f; + } + } +} diff --git a/IFunction.cs b/IFunction.cs new file mode 100644 index 0000000..006d617 --- /dev/null +++ b/IFunction.cs @@ -0,0 +1,11 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace SuperBASIC +{ + interface IFunction + { + public float Apply(List arguments); + } +} diff --git a/Library.cs b/Library.cs new file mode 100644 index 0000000..dee7876 --- /dev/null +++ b/Library.cs @@ -0,0 +1,29 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace SuperBASIC +{ + class Library + { + internal List functions; + internal List arities; + internal Dictionary nameResolution; + + public Library() + { + functions = new List(); + arities = new List(); + nameResolution = new Dictionary(); + } + + public int AddFunction(IFunction fn, int arity, string name) + { + int idx = functions.Count; + functions.Add(fn); + arities.Add(arity); + nameResolution[name] = idx; + return idx; + } + } +} diff --git a/Parser.cs b/Parser.cs new file mode 100644 index 0000000..f0716e3 --- /dev/null +++ b/Parser.cs @@ -0,0 +1,86 @@ +using System; +using System.Collections.Generic; +using System.Text; +using System.IO; +using System.Text.RegularExpressions; + +namespace SuperBASIC +{ + class Parser + { + + [Serializable] + public class ParseException : Exception + { + public ParseException() { } + public ParseException(string message) : base(message) { } + public ParseException(string message, Exception inner) : base(message, inner) { } + protected ParseException( + System.Runtime.Serialization.SerializationInfo info, + System.Runtime.Serialization.StreamingContext context) : base(info, context) { } + } + + readonly Library library; + readonly Runtime runtime; + public Parser(Runtime rt) + { + runtime = rt; + library = rt.lib; + } + + public Bytecode ParseFile(string filepath) + { + Bytecode c = new Bytecode(); + string[] sourceLines = File.ReadAllLines(filepath); + Regex lws = new Regex(@"\s+"); + Regex leadings = new Regex(@"^\s+"); + Regex trailings = new Regex(@"\s+$"); + List codeLines = new List(); + + foreach (string line in sourceLines) + { + string l = lws.Replace(line, " "); + l = leadings.Replace(l, ""); + l = trailings.Replace(l, ""); + + if(l != String.Empty) + { + codeLines.Add(l); + } + } + + foreach(string line in codeLines) + { + var components = line.Split(' '); + + if(!library.nameResolution.ContainsKey(components[0])) + { + throw new ParseException("Unknown operation \"" + components[0] + "\""); + } + + int opcode = library.nameResolution[components[0]]; + int arity = library.arities[opcode]; + + if(arity != components.Length-1) + { + throw new ParseException("Operation " + components[0] + " was provided with the wrong number of arguments: Expected "+arity.ToString()+" found "+(components.Length-1).ToString()); + } + + c.bytecode.Add(new BasicNumber(runtime, opcode)); + foreach (string elem in components.AsSpan(1)) + { + if (elem != "$") + { + c.bytecode.Add(new BasicNumber(runtime, float.Parse(elem))); + } + else + { + c.bytecode.Add(new BasicNumber(runtime)); + } + } + } + + return c; + } + } +} diff --git a/Program.cs b/Program.cs new file mode 100644 index 0000000..feff13b --- /dev/null +++ b/Program.cs @@ -0,0 +1,18 @@ +using System; +using System.IO; + +namespace SuperBASIC +{ + class Program + { + static void Main(string[] args) + { + Library lib = new Library(); + lib.AddFunction(new Functions.Print(), 1, "PRINT"); + lib.AddFunction(new Functions.Multiply(), 2, "MULTIPLY"); + Runtime r = new Runtime(lib); + r.OpenFile(Directory.GetCurrentDirectory() + "\\Test.basic"); + r.Run(); + } + } +} diff --git a/Runtime.cs b/Runtime.cs new file mode 100644 index 0000000..65f5f63 --- /dev/null +++ b/Runtime.cs @@ -0,0 +1,45 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace SuperBASIC +{ + class Runtime + { + float register; + internal Library lib; + Bytecode code; + + public Runtime(Library library) + { + lib = library; + } + + public void OpenFile(string path) + { + code = new Parser(this).ParseFile(path); + } + + public void Run() + { + for(int idx = 0; idx < code.bytecode.Count;) + { + int opcode = code.bytecode[idx].GetOperand(); + int arity = lib.arities[opcode]; + IFunction op = lib.functions[opcode]; + var args = code.bytecode.GetRange(idx + 1, arity); + SetRegister(op.Apply(args)); + idx += arity + 1; + } + } + + internal void SetRegister(float value) + { + register = value; + } + internal float GetRegister() + { + return register; + } + } +} diff --git a/SuperBASIC.csproj b/SuperBASIC.csproj new file mode 100644 index 0000000..fdb69aa --- /dev/null +++ b/SuperBASIC.csproj @@ -0,0 +1,14 @@ + + + + Exe + netcoreapp3.1 + + + + + PreserveNewest + + + + diff --git a/SuperBASIC.sln b/SuperBASIC.sln new file mode 100644 index 0000000..d445c26 --- /dev/null +++ b/SuperBASIC.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.30907.101 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SuperBASIC", "SuperBASIC.csproj", "{51942D92-4C96-4FD9-AA5B-C35661E3B063}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {51942D92-4C96-4FD9-AA5B-C35661E3B063}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {51942D92-4C96-4FD9-AA5B-C35661E3B063}.Debug|Any CPU.Build.0 = Debug|Any CPU + {51942D92-4C96-4FD9-AA5B-C35661E3B063}.Release|Any CPU.ActiveCfg = Release|Any CPU + {51942D92-4C96-4FD9-AA5B-C35661E3B063}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {B03097C8-5C88-49D7-BD8F-EF905E9827EA} + EndGlobalSection +EndGlobal diff --git a/Test.basic b/Test.basic new file mode 100644 index 0000000..15dbbd5 --- /dev/null +++ b/Test.basic @@ -0,0 +1,2 @@ +MULTIPLY 2 3 +PRINT $ \ No newline at end of file