diff --git a/Sixty502DotNet/src/ExpressionEvaluation/Symbols/Functions/BuiltIn/ConcatFunction.cs b/Sixty502DotNet/src/ExpressionEvaluation/Symbols/Functions/BuiltIn/ConcatFunction.cs new file mode 100644 index 0000000..721e264 --- /dev/null +++ b/Sixty502DotNet/src/ExpressionEvaluation/Symbols/Functions/BuiltIn/ConcatFunction.cs @@ -0,0 +1,47 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2017-2022 informedcitizenry +// +// Licensed under the MIT license. See LICENSE for full license information. +// +//----------------------------------------------------------------------------- + +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Sixty502DotNet +{ + public class ConcatFunction : FunctionDefinitionBase + { + public ConcatFunction() + : base("concat", new List + { + new FunctionArg("arr1", variantType: true), + new FunctionArg("arr2", variantType: true) + }) + { + } + + private static Value? ConcatStrings(ArrayValue strVals) + { + if (strVals[0] is Value v1 && v1.IsString && + strVals[1] is Value v2 && v2.IsString) + { + return new Value($"\"{string.Concat(v1.ToString(true), v2.ToString(true))}\""); + } + throw new Error(Errors.TypeMismatchError); + } + + protected override Value? OnInvoke(ArrayValue args) + { + if (args[0] is ArrayValue arr1 && args[1] is ArrayValue arr2 && arr1.TypeCompatible(arr2)) + { + var concatlist = arr1.ToList(); + concatlist.AddRange(arr2.ToList()); + return new ArrayValue(concatlist); + } + return ConcatStrings(args); + } + } +} + diff --git a/Sixty502DotNet/src/ExpressionEvaluation/Symbols/Functions/BuiltIn/FilterFunction.cs b/Sixty502DotNet/src/ExpressionEvaluation/Symbols/Functions/BuiltIn/FilterFunction.cs new file mode 100644 index 0000000..fdf1e12 --- /dev/null +++ b/Sixty502DotNet/src/ExpressionEvaluation/Symbols/Functions/BuiltIn/FilterFunction.cs @@ -0,0 +1,92 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2017-2022 informedcitizenry +// +// Licensed under the MIT license. See LICENSE for full license information. +// +//----------------------------------------------------------------------------- + +using System; +using System.Collections.Generic; +using System.Text; + +namespace Sixty502DotNet +{ + public class FilterFunction : FunctionDefinitionBase + { + public FilterFunction() + : base("filter", new List + { + new FunctionArg("array", variantType: true), + new FunctionArg("predicate", TypeCode.Object) + }) + { + + } + + private static Value? FilterString(Value str, FunctionValue predicate) + { + string strVal = str.ToString(true); + StringBuilder filtered = new(); + foreach(var c in strVal) + { + ArrayValue args = new() + { + new Value($"'{c}'") + }; + Value? match = predicate.Invoke(args); + if (match == null) + { + throw new Error("Predicate did not return a value."); + } + if (match.DotNetType != TypeCode.Boolean) + { + throw new Error(Errors.TypeMismatchError); + } + if (match.ToBool()) + { + filtered.Append(c); + } + } + return new Value($"\"{filtered}\""); + } + + protected override Value? OnInvoke(ArrayValue args) + { + if (args[1] is FunctionValue predicate) + { + if (args[0].IsString) + { + return FilterString(args[0], predicate); + } + if (args[0] is not ArrayValue arr) + { + throw new Error(Errors.TypeMismatchError); + } + ArrayValue filtered = new(); + foreach(var val in arr) + { + ArrayValue args2 = new() + { + val + }; + Value? match = predicate.Invoke(args2); + if (match == null) + { + throw new Error("Predicate did not return a value."); + } + if (match.DotNetType != TypeCode.Boolean) + { + throw new Error(Errors.TypeMismatchError); + } + if (match.ToBool()) + { + filtered.Add(val); + } + } + return filtered; + } + throw new Error("Parameter must be a function expression."); + } + } +} + diff --git a/Sixty502DotNet/src/ExpressionEvaluation/Symbols/Functions/BuiltIn/MapFunction.cs b/Sixty502DotNet/src/ExpressionEvaluation/Symbols/Functions/BuiltIn/MapFunction.cs new file mode 100644 index 0000000..8f0c49a --- /dev/null +++ b/Sixty502DotNet/src/ExpressionEvaluation/Symbols/Functions/BuiltIn/MapFunction.cs @@ -0,0 +1,55 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2017-2022 informedcitizenry +// +// Licensed under the MIT license. See LICENSE for full license information. +// +//----------------------------------------------------------------------------- + +using System; +using System.Collections.Generic; +using System.Text; + +namespace Sixty502DotNet +{ + public class MapFunction : FunctionDefinitionBase + { + public MapFunction() + : base("map", new List + { + new FunctionArg("array", TypeCode.Object), + new FunctionArg("transformFunc", TypeCode.Object) + }) + { + } + + protected override Value? OnInvoke(ArrayValue args) + { + if (args[1] is FunctionValue transformFunc) + { + if (args[0] is not ArrayValue arr) + { + throw new Error(Errors.TypeMismatchError); + } + ArrayValue transformedArray = new ArrayValue(); + foreach (var val in arr) + { + ArrayValue args2 = new ArrayValue(); + args2.Add(val); + Value? transformed = transformFunc.Invoke(args2); + if (transformed == null) + { + throw new Error("Transform function did not return a value."); + } + if (!transformedArray.TypeCompatible(transformed)) + { + throw new Error(Errors.TypeMismatchError); + } + transformedArray.Add(transformed); + } + return transformedArray; + } + throw new Error("Parameter must be a function expression."); + } + } +} + diff --git a/Sixty502DotNet/src/ExpressionEvaluation/Symbols/Functions/BuiltIn/ReduceFunction.cs b/Sixty502DotNet/src/ExpressionEvaluation/Symbols/Functions/BuiltIn/ReduceFunction.cs new file mode 100644 index 0000000..2276a25 --- /dev/null +++ b/Sixty502DotNet/src/ExpressionEvaluation/Symbols/Functions/BuiltIn/ReduceFunction.cs @@ -0,0 +1,56 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2017-2022 informedcitizenry +// +// Licensed under the MIT license. See LICENSE for full license information. +// +//----------------------------------------------------------------------------- + +using System; +using System.Collections.Generic; + +namespace Sixty502DotNet +{ + public class ReduceFunction : FunctionDefinitionBase + { + public ReduceFunction() + : base("reduce", new List + { + new FunctionArg("array", TypeCode.Object), + new FunctionArg("reducer", TypeCode.Object) + }) + { + } + + protected override Value? OnInvoke(ArrayValue args) + { + if (args[1] is FunctionValue reducer) + { + if (args[0] is ArrayValue array) + { + Value reduced = array[0]; + for(int i = 1; i < array.Count; i++) + { + ArrayValue reduceParams = new() + { + reduced, + array[i] + }; + Value? reduction = reducer.Invoke(reduceParams); + if (reduction?.IsDefined != true) + { + throw new Error("Function did not return a value."); + } + if (!reduced.SetAs(reduction!)) + { + throw new Error(Errors.TypeMismatchError); + } + } + return reduced; + } + throw new Error(Errors.TypeMismatchError); + } + throw new Error("Parameter must be a function expression."); + } + } +} + diff --git a/Sixty502DotNet/src/ExpressionEvaluation/Symbols/Functions/BuiltIn/SortFunction.cs b/Sixty502DotNet/src/ExpressionEvaluation/Symbols/Functions/BuiltIn/SortFunction.cs new file mode 100644 index 0000000..2a5d865 --- /dev/null +++ b/Sixty502DotNet/src/ExpressionEvaluation/Symbols/Functions/BuiltIn/SortFunction.cs @@ -0,0 +1,55 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2017-2022 informedcitizenry +// +// Licensed under the MIT license. See LICENSE for full license information. +// +//----------------------------------------------------------------------------- + +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Sixty502DotNet +{ + public class SortFunction : FunctionDefinitionBase + { + public SortFunction() + : base("sort", new List { new FunctionArg("array", variantType: true)} ) + { + + } + + protected override Value? OnInvoke(ArrayValue args) + { + if (args[0].IsString) + { + string argStr = args[0].ToString(true); + return new Value($"\"{string.Concat(argStr.OrderBy(c => c))}\""); + } + if (args[0] is ArrayValue arr) + { + if (arr.ElementsNumeric) + { + var numSorted = arr.OrderBy(v => v.ToDouble()); + return new ArrayValue(numSorted.ToList()); + } + if (arr.ElementType == TypeCode.String) + { + var strSorted = arr.Select(v => v.ToString(true)).ToArray(); + Array.Sort(strSorted, StringComparer.Ordinal); + var sortedArr = new ArrayValue(); + foreach (var s in strSorted) + sortedArr.Add(new Value($"\"{s}\"")); + return sortedArr; + } + if (arr.ElementType == TypeCode.Boolean) + { + var boolSorted = arr.OrderBy(v => v.ToBool()); + return new ArrayValue(boolSorted.ToList()); + } + } + throw new Error(Errors.TypeMismatchError); + } + } +} + diff --git a/Sixty502DotNet/src/ExpressionEvaluation/Symbols/Functions/BuiltIn/UnionFunction.cs b/Sixty502DotNet/src/ExpressionEvaluation/Symbols/Functions/BuiltIn/UnionFunction.cs new file mode 100644 index 0000000..e502af2 --- /dev/null +++ b/Sixty502DotNet/src/ExpressionEvaluation/Symbols/Functions/BuiltIn/UnionFunction.cs @@ -0,0 +1,37 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2017-2022 informedcitizenry +// +// Licensed under the MIT license. See LICENSE for full license information. +// +//----------------------------------------------------------------------------- + +using System; +using System.Collections.Generic; +using System.Linq; + +namespace Sixty502DotNet +{ + public class UnionFunction : FunctionDefinitionBase + { + public UnionFunction() + : base("union", new List + { + new FunctionArg("arr1", TypeCode.Object), + new FunctionArg("arr2", TypeCode.Object) + }) + { + } + + protected override Value? OnInvoke(ArrayValue args) + { + if (args[0] is ArrayValue arr1 && args[1] is ArrayValue arr2 && arr1.TypeCompatible(arr2)) + { + var unionlist = arr1.ToHashSet(); + unionlist.UnionWith(arr2.ToHashSet()); + return new ArrayValue(unionlist.ToList()); + } + throw new NotImplementedException(); + } + } +} + diff --git a/Sixty502DotNet/src/ExpressionEvaluation/ValueTypes/FunctionValue.cs b/Sixty502DotNet/src/ExpressionEvaluation/ValueTypes/FunctionValue.cs new file mode 100644 index 0000000..d39c444 --- /dev/null +++ b/Sixty502DotNet/src/ExpressionEvaluation/ValueTypes/FunctionValue.cs @@ -0,0 +1,31 @@ +//----------------------------------------------------------------------------- +// Copyright (c) 2017-2022 informedcitizenry +// +// Licensed under the MIT license. See LICENSE for full license information. +// +//----------------------------------------------------------------------------- + +namespace Sixty502DotNet +{ + public class FunctionValue : Value + { + private readonly UserFunctionDefinition _fcnDefinition; + + public FunctionValue(Sixty502DotNetParser.ArrowFuncContext arrowCtx, AssemblyServices services) + { + Visitor = new BlockVisitor(services); + _fcnDefinition = UserFunctionDefinition.Declare(arrowCtx, services.Symbols); + Type = typeof(FunctionValue); // just to get the DotNetType + } + + public Value? Invoke(ArrayValue args) + { + _fcnDefinition.Visitor = Visitor; + return _fcnDefinition.Invoke(args); + } + + public override string ToString() => "() =>"; + + public BlockVisitor Visitor { get; init; } + } +} \ No newline at end of file