diff --git a/FAILang/FAILangVisitor.cs b/FAILang/FAILangVisitor.cs index 3a3ba29..68cad9f 100644 --- a/FAILang/FAILangVisitor.cs +++ b/FAILang/FAILangVisitor.cs @@ -151,6 +151,9 @@ public override IType VisitBinary([NotNull] FAILangParser.BinaryContext context) case "^": oper = BinaryOperator.EXPONENT; break; + case "||": + oper = BinaryOperator.CONCAT; + break; case "is": oper = BinaryOperator.IS; break; diff --git a/FAILang/Grammar/FAILang.g4 b/FAILang/Grammar/FAILang.g4 index 4c9b87e..dab58e3 100644 --- a/FAILang/Grammar/FAILang.g4 +++ b/FAILang/Grammar/FAILang.g4 @@ -55,7 +55,7 @@ binary : prefix | binary op=EXPONENT binary | binary op=( MULTIPLY | DIVIDE ) binary - | binary op=( PLUS | SUBTRACT | PLUS_MINUS ) binary + | binary op=( PLUS | SUBTRACT | PLUS_MINUS | CONCAT ) binary | binary op=IS binary ; @@ -182,6 +182,9 @@ DIVIDE EXPONENT : '^' ; +CONCAT + : '||' + ; EQ : '=' ; diff --git a/FAILang/Operator.cs b/FAILang/Operator.cs index c6f41d1..fc0db52 100644 --- a/FAILang/Operator.cs +++ b/FAILang/Operator.cs @@ -18,6 +18,7 @@ public enum BinaryOperator MULTIPLY, DIVIDE, EXPONENT, + CONCAT, IS } public enum RelationalOperator @@ -54,6 +55,8 @@ public static string ToDisplayString(this BinaryOperator op) return "/"; case BinaryOperator.EXPONENT: return "^"; + case BinaryOperator.CONCAT: + return "||"; case BinaryOperator.IS: return "is"; default: diff --git a/FAILang/Types/MathString.cs b/FAILang/Types/MathString.cs index 1e144d1..ef3e313 100644 --- a/FAILang/Types/MathString.cs +++ b/FAILang/Types/MathString.cs @@ -20,7 +20,7 @@ public MathString(string value) public Dictionary> BinaryOperators => new Dictionary>() { - {BinaryOperator.ADD, OpConcat} + {BinaryOperator.CONCAT, OpConcat} }; public Dictionary> RelativeOperators => null; diff --git a/FAILang/Types/Number.cs b/FAILang/Types/Number.cs index 71098e8..4acbefe 100644 --- a/FAILang/Types/Number.cs +++ b/FAILang/Types/Number.cs @@ -26,7 +26,8 @@ public Number(Complex value) {BinaryOperator.PLUS_MINUS, OpPlusMinus}, {BinaryOperator.MULTIPLY, OpMultiply}, {BinaryOperator.DIVIDE, OpDivide}, - {BinaryOperator.EXPONENT, OpExponent} + {BinaryOperator.EXPONENT, OpExponent}, + {BinaryOperator.CONCAT, OpConcat} }; public Dictionary> RelativeOperators => new Dictionary>() { @@ -133,6 +134,18 @@ private IType OpExponent(IOperable other) return null; } } + private IType OpConcat(IOperable other) + { + switch (other) + { + case Number num: + var log = 1 + Complex.Log10(num.value); + Complex floor = new Complex(Math.Floor(log.Real), Math.Floor(log.Imaginary)); + return new Number(num.value + (value * Complex.Pow(10, floor))); + default: + return null; + } + } private MathBool OpEquals(IOperable other) { switch (other) diff --git a/FAILang/Types/Tuple.cs b/FAILang/Types/Tuple.cs index 572a78d..095de09 100644 --- a/FAILang/Types/Tuple.cs +++ b/FAILang/Types/Tuple.cs @@ -6,7 +6,7 @@ namespace FAILang.Types { - struct Tuple : IType, IIndexable + struct Tuple : IIndexable, IOperable { public string TypeName => "Tuple"; public readonly IType[] items; @@ -18,18 +18,29 @@ public Tuple(IType[] items) this.items = items; } - public IType Index(int index) => items[index]; + public Dictionary> BinaryOperators => new Dictionary>() + { + {BinaryOperator.CONCAT, OpConcat} + }; - public IType IndexRange(int left_b, int right_b) + public Dictionary> RelativeOperators => null; + public Dictionary> UnaryOperators => null; + + private IType OpConcat(IOperable other) { - IType[] newTuple = new IType[right_b - left_b + 1]; - for (int i = 0; i <= right_b - left_b; i++) + switch (other) { - newTuple[i] = items[i + left_b]; + case Tuple tup: + return new Tuple(items.Concat(tup.items).ToArray()); + default: + return null; } - return new Tuple(newTuple); } + public IType Index(int index) => items[index]; + + public IType IndexRange(int left_b, int right_b) => new Tuple(items.Skip(left_b).SkipLast(Length - right_b - 1).ToArray()); + public override string ToString() { switch (items.Length) { case 0: diff --git a/FAILang/Types/Unevaluated/IndexerExpression.cs b/FAILang/Types/Unevaluated/IndexerExpression.cs index 3a11d4d..69218df 100644 --- a/FAILang/Types/Unevaluated/IndexerExpression.cs +++ b/FAILang/Types/Unevaluated/IndexerExpression.cs @@ -46,7 +46,7 @@ public IType Evaluate(Dictionary lookups) if (!n_left.IsReal || left != n_left.value.Real) return new Error("IndexError", "Indexer values must be positive integers."); if (!range && (left < 0 || left >= item.Length)) - return new Error("IndexError", $"{left} is out of range."); + return Undefined.instance; } IType t_right = rightIndex; if (rightIndex is IUnevaluated u_right) t_right = u_right.Evaluate(lookups); @@ -56,7 +56,7 @@ public IType Evaluate(Dictionary lookups) if (!n_right.IsReal || right != n_right.value.Real) return new Error("IndexError", "Indexer values must be positive integers."); if (!range && (right < 0 || right >= item.Length)) - return new Error("IndexError", $"{right} is out of range."); + return Undefined.instance; } if (range) @@ -66,7 +66,12 @@ public IType Evaluate(Dictionary lookups) else if (t_left == null && right < left) left = right; if (left > right) - return new Error("IndexError", "The first index in an index range cannot be greater than the second index."); + { + var tmp = left; + left = right; + right = tmp; + } + return item.IndexRange(left, right); } else diff --git a/FAILang/Types/Vector.cs b/FAILang/Types/Vector.cs index 854c353..7b16eaa 100644 --- a/FAILang/Types/Vector.cs +++ b/FAILang/Types/Vector.cs @@ -22,7 +22,8 @@ public Vector(IType[] items) public Dictionary> BinaryOperators => new Dictionary>() { {BinaryOperator.ADD, OpAdd}, {BinaryOperator.SUBTRACT, OpSubtract}, - {BinaryOperator.MULTIPLY, OpMultiply} + {BinaryOperator.MULTIPLY, OpMultiply}, + {BinaryOperator.CONCAT, OpConcat} }; public Dictionary> RelativeOperators => null; @@ -103,6 +104,16 @@ private IType OpMultiply(IOperable other) return null; } } + private IType OpConcat(IOperable other) + { + switch (other) + { + case Vector vec: + return new Vector(items.Concat(vec.items).ToArray()); + default: + return null; + } + } private IType OpNegate() { IType[] newItems = new IType[items.Length]; @@ -132,15 +143,7 @@ private IType OpMagnitude() } public IType Index(int index) => items[index]; - public IType IndexRange(int left_b, int right_b) - { - IType[] newVector = new IType[right_b - left_b + 1]; - for (int i = 0; i <= right_b - left_b; i++) - { - newVector[i] = items[i + left_b]; - } - return new Vector(newVector); - } + public IType IndexRange(int left_b, int right_b) => new Vector(items.Skip(left_b).SkipLast(Length - right_b - 1).ToArray()); public override string ToString() => $"<{String.Join(", ", (object[])items)}>";