Skip to content
This repository has been archived by the owner on Oct 12, 2024. It is now read-only.

Commit

Permalink
Cast, join, split are working./
Browse files Browse the repository at this point in the history
  • Loading branch information
dylanbeattie committed Jul 13, 2024
1 parent 8846a6f commit ee8b7f7
Show file tree
Hide file tree
Showing 9 changed files with 131 additions and 34 deletions.
78 changes: 54 additions & 24 deletions Starship/Rockstar.Engine/RockstarEnvironment.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
using System.Diagnostics;
using System.Threading.Tasks.Dataflow;
using Rockstar.Engine.Expressions;
using Rockstar.Engine.Statements;
using Rockstar.Engine.Values;
using Array = Rockstar.Engine.Values.Array;

namespace Rockstar.Engine;

Expand Down Expand Up @@ -42,11 +45,12 @@ private Variable AssertTarget(Pronoun pronoun)
return variables.ContainsKey(variable.Key) ? this : Parent?.GetScope(variable);
}

private void SetArray(Variable variable, Value index, Value value) {
if (variables.ContainsKey(variable.Key))
throw new($"Can't assign {variable.Name} at index {index} - {variable.Name} is not an indexed variable");
if (!arrays.ContainsKey(variable.Key)) arrays[variable.Key] = new();
arrays[variable.Key][index] = value;
private Value SetArray(Variable variable, Value index, Value value) {
variables.TryAdd(variable.Key, new Array(Source.None));
return variables[variable.Key] switch {
Array array => array.Set(index, value),
_ => throw new($"Can't assign {variable.Name} at index {index} - {variable.Name} is not an indexed variable")
};
}

private void SetLocal(Variable variable, Value value)
Expand All @@ -66,29 +70,19 @@ public Result SetVariable(Variable variable, Value value) {
return new(value);
}

private Value Scalar(Dictionary<Value, Value> array)
=> new Number(1 + array.Keys.Where(k => k is Number).Select(k => Math.Ceiling(((Number) k).Value)).Max());
//private Value Scalar(Dictionary<Value, Value> array)
// => new Number(1 + array.Keys.Where(k => k is Number).Select(k => Math.Ceiling(((Number) k).Value)).Max());

public Value Lookup(Variable variable) {
var key = (variable is Pronoun pronoun ? AssertTarget(pronoun).Key : variable.Key);
var array = LookupArray(key);
var simple = LookupValue(key);
if (variable.Index == default) {
if (simple != default) return simple;
if (array != default) return Scalar(array);
throw new($"Unknown variable '{variable.Name}'");
}
var value = LookupValue(key);
if (variable.Index == default) return value ?? throw new($"Unknown variable '{variable.Name}'");
var index = Eval(variable.Index);
if (array == default) {
if (simple is not Strïng s || index is not Number i) throw new($"Unknown array '{variable.Name}'");
var sValue = s.Value;
var iValue = (int) i.NumericValue;
return (iValue < sValue.Length ? new Strïng(sValue[iValue]) : Mysterious.Instance);
}
var found = array.TryGetValue(index, out var value);
if (found) return value!;
if (index is Number && index.LessThan(Scalar(array)).Truthy) return Mysterious.Instance;
throw new($"Array '{variable.Name}' has no element at {index}");
return (value, index) switch {
(Strïng s, Number i) => s.CharAt(i),
(Array a, _) => a.Get(index),
_ => throw new($"Unknown array '{variable.Name}'")
};
}

private Dictionary<Value, Value>? LookupArray(string key)
Expand Down Expand Up @@ -117,9 +111,45 @@ public Result Exec(Block block) {
Return r => Return(r),
Listen l => Listen(l),
Rounding r => Rounding(r),
Mutation m => Mutation(m),
_ => throw new($"I don't know how to execute {statement.GetType().Name} statements")
};

private Result Mutation(Mutation m)
=> m.Operator switch {
Operator.Join => Join(m),
Operator.Split => Split(m),
Operator.Cast => Cast(m),
_ => throw new($"Unsupported mutation operator {m.Operator}")
};

private Result Cast(Mutation m) {
var input = Eval(m.Expression);
Value value = input switch {
Strïng s => Decimal.TryParse(s.Value, out var d) ? new Number(d) : throw new($"Can't cast '{s.Value}' to a number"),
Number n => new Strïng((char) n.NumericValue),
_ => throw new($"Can't cast expression of type {input.GetType().Name}")
};
if (m.Target != default) SetLocal(m.Target, value);
return new(value);
}
private Result Split(Mutation m) {
var value = Eval(m.Expression);
if (value is not Strïng s) throw new("Only strings can be split.");
var delimiter = m.Modifier == default ? "" : Eval(m.Modifier).ToString();
var array = s.Split(delimiter);
if (m.Target != default) SetLocal(m.Target, array);
return new(array);
}
private Result Join(Mutation m) {
var value = Eval(m.Expression);
if (value is not Array array) throw new("Can't join something which is not an array.");
var joiner = m.Modifier == default ? "" : Eval(m.Modifier).ToString();
var joined = array.Join(joiner);
if (m.Target != default) SetLocal(m.Target, joined);
return new(joined);
}

private Result Rounding(Rounding r) {
var value = Lookup(r.Variable);
if (value is not Number n) throw new($"Can't apply rounding to variable {r.Variable.Name} of type {value.GetType().Name}");
Expand Down
1 change: 0 additions & 1 deletion Starship/Rockstar.Engine/Statements/Statement.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ public enum Round {
public class Rounding(Variable variable, Round round, Source source) : Statement(source) {
public Variable Variable => variable;
public Round Round => round;

}
public class Mutation(Operator op, Expression expr, Source source, Variable? target = default, Expression? modifier = default)
: Statement(source) {
Expand Down
31 changes: 31 additions & 0 deletions Starship/Rockstar.Engine/Values/Array.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
using System.Text;

namespace Rockstar.Engine.Values;

public class Array(Source source)
: Value(source) {
private readonly Dictionary<Value, Value> entries = new();

public Array(Value[] args) : this(Source.None) {
for (var i = 0; i < args.Length; i++) entries.Add(new Number(i), args[i]);
}

public override bool Truthy => entries.Count > 0;

public Value Length
=> new Number(1 + this.entries.Keys.Where(k => k is Number)
.Select(k => (int) ((Number) k).NumericValue)
.Max());

public Value Set(Value index, Value value)
=> entries[index] = value;

public Value Get(Value index)
=> entries.TryGetValue(index, out var value) ? value : Mysterious.Instance;

public Strïng Join(string joiner) {
return new Strïng(String.Join(joiner, this.entries.Where(e => e.Key is Number)
.OrderBy(k => ((Number) k.Key).NumericValue)
.Select(k => k.Value.ToString()).ToArray()));
}
}
1 change: 1 addition & 0 deletions Starship/Rockstar.Engine/Values/Number.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Globalization;
using System.Runtime.InteropServices.Marshalling;
using System.Text;
namespace Rockstar.Engine.Values;

Expand Down
13 changes: 13 additions & 0 deletions Starship/Rockstar.Engine/Values/Strïng.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,14 @@ namespace Rockstar.Engine.Values;

public class Strïng(string value, Source source)
: Value(source) {
public Array Split(string delimiter) {
Strïng[] tokens;
tokens = delimiter == ""
? this.Value.ToCharArray().Select(c => new Strïng(c)).ToArray()
: this.Value.Split(delimiter).Select(s => new Strïng(s)).ToArray();
return new(tokens);
}

public Strïng(string value) : this(value, Source.None) { }
public string Value => value;

Expand Down Expand Up @@ -34,4 +42,9 @@ public Value Repeat(IHaveANumber n)
=> new Strïng(Enumerable
.Range(0, (int) n.NumericValue)
.Select(_ => this.Value));

public Value CharAt(Number number) {
var index = (int) number.NumericValue;
return index < Value.Length ? new Strïng(Value[index]) : Values.Mysterious.Instance;
}
}
1 change: 1 addition & 0 deletions Starship/Rockstar.Engine/Values/Value.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ public override void Print(StringBuilder sb, string prefix)
Strïng s => s,
Null n => Strïng.Null,
Mysterious m => Strïng.Mysterious,
Array a => new(a.Length.ToString()),
_ => throw new NotImplementedException()
};

Expand Down
14 changes: 6 additions & 8 deletions Starship/Rockstar.Engine/rockstar.peg
Original file line number Diff line number Diff line change
Expand Up @@ -346,17 +346,15 @@ mutator <Operator>
/ join
{ Operator.Join }

modifier <Expression>
= _ using _ m:expression
{ m }

mutation <Statement>
= op:mutator _ s:expression _ into _ t:assignable m:modifier
{ new Mutation(op, s, state.Source(), t, m) }
= op:mutator _ s:expression _ into _ t:assignable _ using _ m:expression
{ new Mutation(op, s, state.Source(), target: t, m) }
/ op:mutator _ s:expression _ into _ t:assignable
{ new Mutation(op, s, state.Source(), t) }
{ new Mutation(op, s, state.Source(), target: t) }
/op:mutator _ s:assignable _ using _ m:expression
{ new Mutation(op, s, state.Source(), target: s, modifier: m) }
/ op:mutator _ s:assignable
{ new Mutation(op, s, state.Source()) }
{ new Mutation(op, s, state.Source(), target: s) }

rounding <Statement>
= floor / ceil / math_round
Expand Down
24 changes: 24 additions & 0 deletions Starship/Rockstar.Test/ParserTests/ArrayTests.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,29 @@
namespace Rockstar.Test.ParserTests;

public class MutationTests(ITestOutputHelper output) : ParserTestBase(output) {
[Fact]
public void JoinWorks() {
var source = """
Let the array at 0 be "a"
Let the array at 1 be "b"
Let the array at 2 be "c"
Join the array into ResultA
Shout ResultA
Join the array into ResultB with "-"
Shout ResultB
Join the array
Shout the array
Split "abcde" into tokens
Join tokens with ";"
Shout tokens
""";
var parsed = Parse(source);
}
}
public class ArrayTests(ITestOutputHelper testOutput) : ParserTestBase(testOutput) {

[Fact]
Expand Down
2 changes: 1 addition & 1 deletion Starship/Rockstar.Test/Rockstar.Test.v3.ncrunchproject
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<ProjectConfiguration>
<Settings>
<DefaultTestTimeout>5000</DefaultTestTimeout>
<DefaultTestTimeout>1000</DefaultTestTimeout>
</Settings>
</ProjectConfiguration>

0 comments on commit ee8b7f7

Please sign in to comment.