Skip to content

Commit

Permalink
add if/then/else functions
Browse files Browse the repository at this point in the history
  • Loading branch information
szensk committed Nov 21, 2017
1 parent 3c7e53b commit 15b5066
Show file tree
Hide file tree
Showing 12 changed files with 103 additions and 36 deletions.
4 changes: 2 additions & 2 deletions Wul/Interpreter/Bool.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
{
class Bool : IValue
{
public static Bool True => new Bool(true);
public static Bool False => new Bool(false);
public static Bool True = new Bool(true);
public static Bool False = new Bool(false);

public readonly bool Value;

Expand Down
14 changes: 9 additions & 5 deletions Wul/Interpreter/Function.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using Wul.Parser;

namespace Wul.Interpreter
Expand Down Expand Up @@ -27,12 +28,15 @@ public IValue Evaluate(List<IValue> arguments, Scope scope)
{
string argName = ArgumentNames[i];
currentScope[argName] = arguments[i];
Debug.WriteLine($"Binding {argName} = {arguments[i].AsString()}");
}

return WulInterpreter.Interpret(Body, currentScope);
IValue result = WulInterpreter.Interpret(Body, currentScope);
Debug.WriteLine($"Returning {result.AsString()}");
return result;
}

public virtual void Execute(ListNode list, Scope scope)
public virtual IValue Execute(ListNode list, Scope scope)
{
throw new NotImplementedException();
}
Expand Down Expand Up @@ -62,7 +66,7 @@ public IValue Evaluate(List<IValue> arguments, Scope scope)
return Body(arguments, scope);
}

public virtual void Execute(ListNode list, Scope scope)
public virtual IValue Execute(ListNode list, Scope scope)
{
throw new NotImplementedException();
}
Expand Down Expand Up @@ -91,9 +95,9 @@ public IValue Evaluate(List<IValue> arguments, Scope scope)
throw new NotImplementedException();
}

public virtual void Execute(ListNode list, Scope scope)
public virtual IValue Execute(ListNode list, Scope scope)
{
Body(list, scope);
return Body(list, scope);
}

public string AsString()
Expand Down
8 changes: 7 additions & 1 deletion Wul/Interpreter/GlobalScope.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,12 @@ public static void RegisterDefaultFunctions()

//Comparison
Scope["="] = StdLib.Comparison.Equal;
Scope["<"] = StdLib.Comparison.LessThan;

//Conditional
Scope["if"] = StdLib.General.If;
Scope["then"] = StdLib.General.Then;
Scope["else"] = StdLib.General.Then; //Not a typo!

//Bools
Scope["true"] = Bool.True;
Expand All @@ -29,7 +35,7 @@ public static void RegisterDefaultFunctions()
//Arith
Scope["+"] = StdLib.Arithmetic.Add;
Scope["-"] = StdLib.Arithmetic.Subtract;
Scope["<"] = StdLib.Arithmetic.LessThan;
Scope["*"] = StdLib.Arithmetic.Multiply;
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion Wul/Interpreter/IFunction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@ interface IFunction : IValue
string Name { get; }
List<string> ArgumentNames { get; }
IValue Evaluate(List<IValue> arguments, Scope scope);
void Execute(ListNode list, Scope scope);
IValue Execute(ListNode list, Scope scope);
}
}
5 changes: 5 additions & 0 deletions Wul/Interpreter/ListTable.cs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,11 @@ public override void Assign(IValue key, IValue value)

public override Number Count => _list.Count;

public override string AsString()
{
return "(" + string.Join(", ", _list.Select(s => s.AsString()).ToList()) + ")";
}

public override IValue this[IValue key]
{
get => Get(key);
Expand Down
2 changes: 1 addition & 1 deletion Wul/Interpreter/Table.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ abstract class Table : IValue

public abstract Number Count { get; }

public string AsString()
public virtual string AsString()
{
return $"List[{Count.Value}]";
}
Expand Down
14 changes: 10 additions & 4 deletions Wul/Interpreter/WulInterpreter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ private static IValue Evaluate(ListNode list, Scope currentScope = null)
}
else if (first is ListNode)
{
value = Evaluate((ListNode) first);
value = Evaluate((ListNode) first, currentScope);
}

IFunction function = value as IFunction;
Expand All @@ -96,14 +96,20 @@ private static IValue Evaluate(ListNode list, Scope currentScope = null)
{
//Invoke a magic function
//Magic functions do not have their arguments evaluated, it's up the function to do so
magicFunction.Execute(list, currentScope);
value = Value.Nil;
value = magicFunction.Execute(list, currentScope);
}
else
{
//Evaluate a list
var remaining = list.Children.Select(node => Interpret(node, currentScope)).ToArray();
value = new ListTable(remaining);
if (remaining.Length > 1)
{
value = new ListTable(remaining);
}
else if (remaining.Length == 1)
{
value = remaining[0];
}
}

return value;
Expand Down
12 changes: 6 additions & 6 deletions Wul/Parser/List.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,27 +32,27 @@ public override SyntaxNode Parse(string token)
List<SyntaxNode> children = new List<SyntaxNode>();

int currentIndex = 0;
int openParenthesis = 0;
int closeParenthesis = 0;
int openParentheses = 0;
int closeParentheses = 0;
int startIndex = 0;
while (currentIndex < inner.Length)
{
if (inner[currentIndex] == '(')
{
openParenthesis++;
openParentheses++;
}
else if (inner[currentIndex] == ')')
{
closeParenthesis++;
closeParentheses++;
}

if (closeParenthesis > openParenthesis)
if (closeParentheses > openParentheses)
{
throw new Exception("Mismatched parenthesis, have fun");
}

currentIndex++;
if ((currentIndex == inner.Length || inner[currentIndex] == ' ' || inner[currentIndex] == ')') && openParenthesis == closeParenthesis)
if ((currentIndex == inner.Length || inner[currentIndex] == ' ' || inner[currentIndex] == ')') && openParentheses == closeParentheses)
{
string currentInner = inner.Substring(startIndex, currentIndex - startIndex);
var item = Parse(currentInner) ?? identifierParser.Parse(currentInner) ?? numericParser.Parse(currentInner);
Expand Down
31 changes: 16 additions & 15 deletions Wul/StdLib/Arithmetic.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,20 +16,6 @@ internal class Arithmetic
return (Number) sum;
}, "+");

internal static IFunction LessThan = new NetFunction((list, scope) =>
{
var first = list.First() as Number;
var second = list.Skip(1).First() as Number;
if (first.Value < second.Value)
{
return (Number) 1;
}
else
{
return (Number) 0;
}
}, "<");

internal static IFunction Subtract = new NetFunction((list, scope) =>
{
var first = list.First() as Number;
Expand All @@ -40,6 +26,21 @@ internal class Arithmetic
}
double sum = numbers.Sum(x => x.Value);
return (Number) (first.Value - sum);
}, "+");
}, "-");

internal static IFunction Multiply = new NetFunction((list, scope) =>
{
var numbers = list.Select(x => x as Number).Where(x => x != null).ToArray();
if (!numbers.Any())
{
return Value.Nil;
}
double multiplied = numbers[0];
for (int i = 1; i < numbers.Length; ++i)
{
multiplied *= numbers[i];
}
return (Number)multiplied;
}, "*");
}
}
9 changes: 9 additions & 0 deletions Wul/StdLib/Comparison.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,14 @@ internal class Comparison
bool equal = first.Equals(second);
return equal ? Bool.True : Bool.False;
}, "=");

internal static IFunction LessThan = new NetFunction((list, scope) =>
{
Number first = list[0] as Number;
Number second = list[1] as Number;
//TODO make all IValue override Equals
bool lessThan = first.Value < second.Value;
return lessThan ? Bool.True : Bool.False;
}, "<");
}
}
36 changes: 36 additions & 0 deletions Wul/StdLib/General.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,5 +33,41 @@ class General
return function;
}, "def");

internal static IFunction Then = new NetFunction((list, scope) =>
{
if (list.Count == 1)
{
return list.First();
}
else
{
return new ListTable(list.ToArray());
}
}, "then/else");

internal static IFunction If = new MagicNetFunction((list, scope) =>
{
var children = list.Children.Skip(1).ToArray();
var condition = children[0];
var result = WulInterpreter.Interpret(condition, scope);
var listChildren = children.OfType<ListNode>();
IValue returnValue = Value.Nil;
if (result != Value.Nil && result != Bool.False)
{
var thenBlock = listChildren.FirstOrDefault(l => (l.Children.First() as IdentifierNode)?.Name == "then");
returnValue = WulInterpreter.Interpret(thenBlock, scope);
}
else
{
var elseBlock = listChildren.FirstOrDefault(l => (l.Children.First() as IdentifierNode)?.Name == "else");
returnValue = WulInterpreter.Interpret(elseBlock, scope);
}
return returnValue;
}, "if");
}
}
2 changes: 1 addition & 1 deletion Wul/Wul.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ class Wul
{
static void Main(string[] args)
{
//built ins: def, if, -, <, then, else
//built ins: if, then, else
var parser = new ProgramParser();
Global.RegisterDefaultFunctions();

Expand Down

0 comments on commit 15b5066

Please sign in to comment.