Implemented closure and therefore recursion
This commit is contained in:
parent
ab38d85465
commit
352fa9616e
@ -6,6 +6,7 @@ using System.Collections.Immutable;
|
||||
using AST = Finn.AST;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Net;
|
||||
using Finn.AST;
|
||||
|
||||
namespace Finn;
|
||||
|
||||
@ -80,14 +81,6 @@ public record NativeFunction(Func<object[], object> Function) : Callable
|
||||
public override string ToString() => "<native func>";
|
||||
}
|
||||
|
||||
public class UserFunction : Callable
|
||||
{
|
||||
public object Call(Interpreter interpreter, object[] arguments)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
public class Interpreter : AST.IExprVisitor<Env, object>
|
||||
{
|
||||
private class PatternMismatchException : Exception
|
||||
@ -299,11 +292,25 @@ public class Interpreter : AST.IExprVisitor<Env, object>
|
||||
}
|
||||
}
|
||||
|
||||
private readonly Env globals = new Env();
|
||||
public record FinnFunction(FuncBinding binding, Env closure) : Callable
|
||||
{
|
||||
public object Call(Interpreter interpreter, object[] arguments)
|
||||
{
|
||||
Env env = new Env(closure);
|
||||
for (int i = 0; i < binding.Params.Length; i++)
|
||||
{
|
||||
binding.Params[i].accept((arguments[i], env), new PatternBinder());
|
||||
}
|
||||
return interpreter.evaluate(env, binding.Value);
|
||||
// throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
protected internal readonly Env Globals = new Env();
|
||||
|
||||
public Interpreter()
|
||||
{
|
||||
globals["clock"] = new NativeFunction((args) =>
|
||||
Globals["clock"] = new NativeFunction((args) =>
|
||||
{
|
||||
return (double)DateTimeOffset.Now.ToUnixTimeSeconds();
|
||||
});
|
||||
@ -313,7 +320,7 @@ public class Interpreter : AST.IExprVisitor<Env, object>
|
||||
{
|
||||
try
|
||||
{
|
||||
var value = evaluate(globals, expression);
|
||||
var value = evaluate(Globals, expression);
|
||||
Console.WriteLine(value);
|
||||
}
|
||||
catch (RuntimeError err)
|
||||
@ -475,14 +482,14 @@ public class Interpreter : AST.IExprVisitor<Env, object>
|
||||
catch { return new Variant("nothing", null); }
|
||||
}
|
||||
|
||||
public object visitLetExpr(Env env, AST.Let expr)
|
||||
public object visitLetExpr(Env env, Let expr)
|
||||
{
|
||||
var newEnv = new Env(env);
|
||||
foreach (var binding in expr.Bindings)
|
||||
{
|
||||
switch (binding)
|
||||
{
|
||||
case AST.VarBinding(var pattern, var valueExpr):
|
||||
case VarBinding(var pattern, var valueExpr):
|
||||
var value = evaluate(env, valueExpr);
|
||||
try
|
||||
{
|
||||
@ -496,8 +503,11 @@ public class Interpreter : AST.IExprVisitor<Env, object>
|
||||
throw new RuntimeError(start, e.Message);
|
||||
}
|
||||
break;
|
||||
case FuncBinding fb:
|
||||
newEnv[(string)fb.Name.Literal!] = new FinnFunction(fb, newEnv);
|
||||
break;
|
||||
default:
|
||||
throw new NotImplementedException("TODO function bindings");
|
||||
throw new Exception("wtf there are no other binding types");
|
||||
}
|
||||
}
|
||||
return evaluate(newEnv, expr.Body);
|
||||
|
@ -237,8 +237,7 @@ class Parser
|
||||
}
|
||||
var letToken = previous();
|
||||
|
||||
List<Binding> bindings = new List<Binding>();
|
||||
bindings.Add(parseBinding());
|
||||
List<Binding> bindings = new List<Binding> { parseBinding() };
|
||||
while (match(TokenType.And))
|
||||
{
|
||||
bindings.Add(parseBinding());
|
||||
@ -252,7 +251,7 @@ class Parser
|
||||
Pattern p = pattern();
|
||||
switch (p)
|
||||
{
|
||||
case (SimplePattern(var funcName)) when funcName != null && match(TokenType.LParen):
|
||||
case SimplePattern(var funcName) when funcName != null && match(TokenType.LParen):
|
||||
List<Pattern> funcParams = new List<Pattern>();
|
||||
while (!check(TokenType.RParen))
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user