├── ECMA262.pdf ├── References ├── xunit.dll ├── FParsec.dll └── FParsecCS.dll ├── Machete.RegExp ├── Limit.fs ├── FunctionTypes.fs ├── MatchResult.fs ├── RegExpFlags.fs ├── RegExp.fs ├── Interpreter.fs ├── MatchState.fs ├── RegExpTree.fs ├── Captures.fs └── RegExpInfo.fs ├── Machete.Core ├── INull.cs ├── IReferenceBase.cs ├── IUndefined.cs ├── IHasInstance.cs ├── IObjectEnvironmentRecord.cs ├── Generators │ ├── GeneratorStep.cs │ ├── Generator.cs │ └── GeneratorSteps.cs ├── IBoolean.cs ├── IBuiltinFunction.cs ├── INumber.cs ├── IString.cs ├── IPrimitiveWrapper.cs ├── IConstructable.cs ├── ICallable.cs ├── Code.cs ├── LanguageTypeCode.cs ├── IArgs.cs ├── IDeclarativeEnvironmentRecord.cs ├── IReference.cs ├── IObjectBuilder.cs ├── IExecutionContext.cs ├── ILexicalEnvironment.cs ├── IEnvironmentRecord.cs ├── IFunction.cs ├── MacheteRuntimeException.cs ├── IPropertyDescriptor.cs ├── BuiltinFunctionAttribute.cs ├── FunctionDeclaration.cs ├── MacheteException.cs ├── IObject.cs ├── ExecutableCode.cs ├── Output.cs ├── DataDescriptorAttribute.cs ├── ReadOnlyList.cs ├── Properties │ └── AssemblyInfo.cs ├── Iterator.cs └── IDynamic.cs ├── Machete.Interactive ├── Command.fs ├── Program.fs ├── AssemblyInfo.fs ├── CommandParser.fs ├── App.config └── Interactive.fs ├── Machete.Tests ├── Standard Built-in ECMAScript Objects │ ├── ErrorObjects.cs │ ├── BooleanObjects.cs │ ├── JsonObject.cs │ └── FunctionObjects.cs ├── Specification │ └── Tests_07_Lexical_Conventions │ │ ├── Tests_07_05_Tokens.cs │ │ ├── Tests_07_08_Literals.cs │ │ ├── Tests_07_07_Punctuators.cs │ │ ├── Tests_07_04_Comments.cs │ │ ├── Tests_07_09_Automatic_Semicolon_Insertion.cs │ │ ├── Tests_07_06_Identifier_Names_and_Identifiers.cs │ │ ├── Tests_07_03_LineTerminators.cs │ │ └── Tests_07_02_WhiteSpace.cs ├── Expressions │ ├── CommaOperator.cs │ ├── ConditionalOperator.cs │ ├── BinaryLogicalOperators.cs │ ├── PostfixExpressions.cs │ ├── AdditiveOperators.cs │ ├── MultiplicativeOperators.cs │ ├── BinaryBitwiseOperators.cs │ ├── BitwiseShiftOperators.cs │ ├── RelationalOperators.cs │ ├── LeftHandSideExpressions.cs │ ├── EqualityOperators.cs │ ├── UnaryOperators.cs │ ├── GeneratorExpression.cs │ └── AssignmentOperators.cs ├── Statements │ ├── EmptyStatement.cs │ ├── Block.cs │ ├── DebuggerStatement.cs │ ├── ThrowStatement.cs │ ├── SwitchStatement.cs │ ├── ReturnStatement.cs │ ├── WithStatement.cs │ ├── IfStatement.cs │ ├── LabelledStatement.cs │ ├── BreakStatement.cs │ ├── ContinueStatement.cs │ ├── TryStatement.cs │ ├── VariableStatement.cs │ └── ForeachStatement.cs ├── Lexical Conventions │ ├── Comments.cs │ ├── LineTerminators.cs │ ├── StringLiteral.cs │ ├── WhiteSpace.cs │ └── NumericLiteral.cs └── Properties │ └── AssemblyInfo.cs ├── Machete.Parser ├── ElementData.fs └── InputElement.fs ├── Machete.Runtime ├── HostObjects │ ├── HFileSystem.cs │ ├── Iterables │ │ ├── HMapIterable.cs │ │ ├── HFilterIterable.cs │ │ ├── HIterableBase.cs │ │ ├── HStringIterator.cs │ │ ├── HIteratorBase.cs │ │ ├── HGeneratorIterable.cs │ │ ├── HMapIterator.cs │ │ ├── HFilterIterator.cs │ │ ├── HArrayIterator.cs │ │ ├── HGeneratorIterator.cs │ │ └── HIterable.cs │ ├── HOutput.cs │ └── HLazy.cs ├── NativeObjects │ ├── NError.cs │ ├── NUriError.cs │ ├── NEvalError.cs │ ├── NRangeError.cs │ ├── NTypeError.cs │ ├── NSyntaxError.cs │ ├── NBoolean.cs │ ├── NReferenceError.cs │ ├── NArguments.cs │ ├── NNumber.cs │ ├── NRegExp.cs │ ├── NDate.cs │ ├── BuiltinObjects │ │ ├── PUriError.cs │ │ ├── PEvalError.cs │ │ ├── PTypeError.cs │ │ ├── PRangeError.cs │ │ ├── PSyntaxError.cs │ │ ├── PReferenceError.cs │ │ ├── BFunction.cs │ │ ├── BConstructor.cs │ │ ├── CBoolean.cs │ │ ├── BJson.cs │ │ ├── CError.cs │ │ ├── CEvalError.cs │ │ ├── CUriError.cs │ │ ├── CTypeError.cs │ │ ├── CRangeError.cs │ │ ├── CSyntaxError.cs │ │ ├── CReferenceError.cs │ │ ├── PError.cs │ │ ├── CString.cs │ │ ├── CNumber.cs │ │ ├── CFunction.cs │ │ ├── PBoolean.cs │ │ ├── CArray.cs │ │ └── CRegExp.cs │ ├── NString.cs │ └── NBoundFunction.cs ├── Properties │ └── AssemblyInfo.cs ├── ExecutionContext.cs └── RuntimeTypes │ ├── SpecificationTypes │ ├── SPropertyDescriptor.cs │ ├── SArgs.cs │ ├── SLexicalEnvironment.cs │ ├── SObjectEnvironmentRecord.cs │ └── SDeclarativeEnvironmentRecord.cs │ └── LanguageTypes │ ├── LNull.cs │ ├── LUndefined.cs │ ├── LBoolean.cs │ └── LString.cs ├── .gitignore ├── README.markdown ├── Machete.Compiler ├── FloatParser.fs ├── AssemblyInfo.fs └── IntParser.fs └── Machete ├── AssemblyInfo.fs └── Engine.fs /ECMA262.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ChaosPandion/Machete/HEAD/ECMA262.pdf -------------------------------------------------------------------------------- /References/xunit.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ChaosPandion/Machete/HEAD/References/xunit.dll -------------------------------------------------------------------------------- /References/FParsec.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ChaosPandion/Machete/HEAD/References/FParsec.dll -------------------------------------------------------------------------------- /References/FParsecCS.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ChaosPandion/Machete/HEAD/References/FParsecCS.dll -------------------------------------------------------------------------------- /Machete.RegExp/Limit.fs: -------------------------------------------------------------------------------- 1 | namespace Machete.RegExp 2 | 3 | type Limit = 4 | | Finite of int 5 | | Infinite 6 | -------------------------------------------------------------------------------- /Machete.Core/INull.cs: -------------------------------------------------------------------------------- 1 | namespace Machete.Core 2 | { 3 | public interface INull : IDynamic 4 | { 5 | 6 | } 7 | } -------------------------------------------------------------------------------- /Machete.Core/IReferenceBase.cs: -------------------------------------------------------------------------------- 1 | namespace Machete.Core 2 | { 3 | public interface IReferenceBase 4 | { 5 | 6 | } 7 | } -------------------------------------------------------------------------------- /Machete.Core/IUndefined.cs: -------------------------------------------------------------------------------- 1 | namespace Machete.Core 2 | { 3 | public interface IUndefined : IDynamic, IReferenceBase 4 | { 5 | 6 | } 7 | } -------------------------------------------------------------------------------- /Machete.Interactive/Command.fs: -------------------------------------------------------------------------------- 1 | namespace Machete.Interactive 2 | 3 | type Command = 4 | | GetTimeout 5 | | SetTimeout of int 6 | | Echo of string 7 | 8 | 9 | -------------------------------------------------------------------------------- /Machete.RegExp/FunctionTypes.fs: -------------------------------------------------------------------------------- 1 | namespace Machete.RegExp 2 | 3 | type PatternMatcher = string -> int -> MatchResult 4 | 5 | type Matcher = MatchState -> MatchResult -------------------------------------------------------------------------------- /Machete.Core/IHasInstance.cs: -------------------------------------------------------------------------------- 1 | namespace Machete.Core 2 | { 3 | public interface IHasInstance 4 | { 5 | bool HasInstance(IDynamic value); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /Machete.Core/IObjectEnvironmentRecord.cs: -------------------------------------------------------------------------------- 1 | namespace Machete.Core 2 | { 3 | public interface IObjectEnvironmentRecord : IEnvironmentRecord 4 | { 5 | 6 | } 7 | } -------------------------------------------------------------------------------- /Machete.Core/Generators/GeneratorStep.cs: -------------------------------------------------------------------------------- 1 | namespace Machete.Core.Generators 2 | { 3 | public delegate bool GeneratorStep(IEnvironment environment, Generator generator); 4 | } -------------------------------------------------------------------------------- /Machete.Core/IBoolean.cs: -------------------------------------------------------------------------------- 1 | namespace Machete.Core 2 | { 3 | public interface IBoolean : IDynamic, IReferenceBase 4 | { 5 | bool BaseValue { get; } 6 | } 7 | } -------------------------------------------------------------------------------- /Machete.Core/IBuiltinFunction.cs: -------------------------------------------------------------------------------- 1 | namespace Machete.Core 2 | { 3 | public interface IBuiltinFunction : ICallable, IConstructable, IHasInstance 4 | { 5 | 6 | } 7 | } -------------------------------------------------------------------------------- /Machete.Core/INumber.cs: -------------------------------------------------------------------------------- 1 | namespace Machete.Core 2 | { 3 | public interface INumber : IDynamic, IReferenceBase 4 | { 5 | double BaseValue { get; } 6 | } 7 | } -------------------------------------------------------------------------------- /Machete.Core/IString.cs: -------------------------------------------------------------------------------- 1 | namespace Machete.Core 2 | { 3 | public interface IString : IDynamic, IReferenceBase 4 | { 5 | string BaseValue { get; } 6 | } 7 | } -------------------------------------------------------------------------------- /Machete.Core/IPrimitiveWrapper.cs: -------------------------------------------------------------------------------- 1 | namespace Machete.Core 2 | { 3 | public interface IPrimitiveWrapper 4 | { 5 | IDynamic PrimitiveValue { get; set; } 6 | } 7 | } -------------------------------------------------------------------------------- /Machete.Core/IConstructable.cs: -------------------------------------------------------------------------------- 1 | namespace Machete.Core 2 | { 3 | public interface IConstructable 4 | { 5 | IObject Construct(IEnvironment environment, IArgs args); 6 | } 7 | } -------------------------------------------------------------------------------- /Machete.Core/ICallable.cs: -------------------------------------------------------------------------------- 1 | namespace Machete.Core 2 | { 3 | public interface ICallable 4 | { 5 | IDynamic Call(IEnvironment environment, IDynamic thisBinding, IArgs args); 6 | } 7 | } -------------------------------------------------------------------------------- /Machete.RegExp/MatchResult.fs: -------------------------------------------------------------------------------- 1 | namespace Machete.RegExp 2 | 3 | type MatchResult (success:bool, matchState:MatchState) = 4 | member x.Success = success 5 | member x.MatchState = matchState 6 | -------------------------------------------------------------------------------- /Machete.Tests/Standard Built-in ECMAScript Objects/ErrorObjects.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Xunit; 3 | 4 | namespace Machete.Tests 5 | { 6 | public class ErrorObjects : TestBase 7 | { 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /Machete.RegExp/RegExpFlags.fs: -------------------------------------------------------------------------------- 1 | namespace Machete.RegExp 2 | 3 | open System 4 | 5 | [] 6 | type RegExpFlags = 7 | | None = 0x00000000 8 | | Global = 0x00000001 9 | | IgnoreCase = 0x00000002 10 | | Multiline = 0x00000004 11 | -------------------------------------------------------------------------------- /Machete.Core/Code.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace Machete.Core 7 | { 8 | public delegate IDynamic Code(IEnvironment environment, IArgs args); 9 | } 10 | -------------------------------------------------------------------------------- /Machete.Core/LanguageTypeCode.cs: -------------------------------------------------------------------------------- 1 | namespace Machete.Core 2 | { 3 | public enum LanguageTypeCode 4 | { 5 | Undefined, 6 | Null, 7 | Boolean, 8 | String, 9 | Number, 10 | Object 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /Machete.Parser/ElementData.fs: -------------------------------------------------------------------------------- 1 | namespace Machete.Parser 2 | 3 | type ElementData = { 4 | line : int64 5 | column : int64 6 | } with 7 | override x.ToString () = 8 | System.String.Format("(Ln {0}, Col {1})", x.line, x.column) 9 | 10 | -------------------------------------------------------------------------------- /Machete.Core/IArgs.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Machete.Core 4 | { 5 | public interface IArgs : IEnumerable 6 | { 7 | IDynamic this[int index] { get; } 8 | int Count { get; } 9 | bool IsEmpty { get; } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Machete.Core/IDeclarativeEnvironmentRecord.cs: -------------------------------------------------------------------------------- 1 | namespace Machete.Core 2 | { 3 | public interface IDeclarativeEnvironmentRecord : IEnvironmentRecord 4 | { 5 | void CreateImmutableBinding(string name); 6 | void InitializeImmutableBinding(string name, IDynamic value); 7 | } 8 | } -------------------------------------------------------------------------------- /Machete.Tests/Specification/Tests_07_Lexical_Conventions/Tests_07_05_Tokens.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace Machete.Tests.Specification.Tests_07_Lexical_Conventions 7 | { 8 | class Tests_07_05_Tokens 9 | { 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Machete.Tests/Specification/Tests_07_Lexical_Conventions/Tests_07_08_Literals.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace Machete.Tests.Specification.Tests_07_Lexical_Conventions 7 | { 8 | class Tests_07_08_Literals 9 | { 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Machete.Tests/Specification/Tests_07_Lexical_Conventions/Tests_07_07_Punctuators.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace Machete.Tests.Specification.Tests_07_Lexical_Conventions 7 | { 8 | class Tests_07_07_Punctuators 9 | { 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Machete.Tests/Specification/Tests_07_Lexical_Conventions/Tests_07_04_Comments.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace Machete.Tests.Specification.Tests_07_Lexical_Conventions 7 | { 8 | public class Tests_07_04_Comments 9 | { 10 | 11 | } 12 | } -------------------------------------------------------------------------------- /Machete.Interactive/Program.fs: -------------------------------------------------------------------------------- 1 | namespace Machete.Interactive 2 | 3 | open System 4 | open FParsec 5 | open FParsec.Primitives 6 | open FParsec.CharParsers 7 | open Machete.Parser.InputElementParsers 8 | open Machete.RegExp 9 | 10 | module Program = 11 | 12 | let main () = 13 | Interactive.initialize() 14 | 15 | 16 | main() -------------------------------------------------------------------------------- /Machete.Tests/Specification/Tests_07_Lexical_Conventions/Tests_07_09_Automatic_Semicolon_Insertion.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace Machete.Tests.Specification.Tests_07_Lexical_Conventions 7 | { 8 | class Tests_07_09_Automatic_Semicolon_Insertion 9 | { 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Machete.Runtime/HostObjects/HFileSystem.cs: -------------------------------------------------------------------------------- 1 | using Machete.Core; 2 | using Machete.Runtime.RuntimeTypes.LanguageTypes; 3 | 4 | namespace Machete.Runtime.HostObjects 5 | { 6 | public sealed class HFileSystem : LObject 7 | { 8 | public HFileSystem(IEnvironment environment) 9 | : base(environment) 10 | { 11 | 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /Machete.Tests/Specification/Tests_07_Lexical_Conventions/Tests_07_06_Identifier_Names_and_Identifiers.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace Machete.Tests.Specification.Tests_07_Lexical_Conventions 7 | { 8 | class Tests_07_06_Identifier_Names_and_Identifiers 9 | { 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Machete.Core/IReference.cs: -------------------------------------------------------------------------------- 1 | namespace Machete.Core 2 | { 3 | public interface IReference : IDynamic 4 | { 5 | IReferenceBase Base { get; } 6 | string Name { get; } 7 | bool IsStrictReference { get; } 8 | bool HasPrimitiveBase { get; } 9 | bool IsPropertyReference { get; } 10 | bool IsUnresolvableReference { get; } 11 | } 12 | } -------------------------------------------------------------------------------- /Machete.Tests/Expressions/CommaOperator.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Xunit; 3 | 4 | namespace Machete.Tests 5 | { 6 | public class CommaOperator : TestBase 7 | { 8 | [Fact(DisplayName = "11.14 Comma Operator ( , )")] 9 | public void Test1114() 10 | { 11 | Assert.True((bool)Engine.ExecuteScript("var x = false; x = true, false; x;")); 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /Machete.Tests/Expressions/ConditionalOperator.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Xunit; 3 | 4 | namespace Machete.Tests 5 | { 6 | public class ConditionalOperator : TestBase 7 | { 8 | [Fact(DisplayName = "11.12 Conditional Operator ( ? : )")] 9 | public void Test1112() 10 | { 11 | Assert.True((bool)Engine.ExecuteScript("true ? true : false")); 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /Machete.Core/IObjectBuilder.cs: -------------------------------------------------------------------------------- 1 | namespace Machete.Core 2 | { 3 | public interface IObjectBuilder 4 | { 5 | IObjectBuilder SetAttributes(bool? writable, bool? enumerable, bool? configurable); 6 | IObjectBuilder AppendDataProperty(string name, IDynamic value); 7 | IObjectBuilder AppendAccessorProperty(string name, IDynamic get, IDynamic set); 8 | IObject ToObject(); 9 | } 10 | } -------------------------------------------------------------------------------- /Machete.Runtime/NativeObjects/NError.cs: -------------------------------------------------------------------------------- 1 | using Machete.Core; 2 | using Machete.Runtime.RuntimeTypes.LanguageTypes; 3 | 4 | namespace Machete.Runtime.NativeObjects 5 | { 6 | public sealed class NError : LObject 7 | { 8 | public NError(IEnvironment environment) 9 | : base(environment) 10 | { 11 | Class = "Error"; 12 | Extensible = true; 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Machete.Tests/Statements/EmptyStatement.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Xunit; 3 | 4 | namespace Machete.Tests 5 | { 6 | public class EmptyStatement : TestBase 7 | { 8 | [Fact(DisplayName = "12.3 Empty Statement")] 9 | public void Test123() 10 | { 11 | const string script = @";"; 12 | Assert.Equal("undefined", (string)Engine.ExecuteScript(script)); 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /Machete.Core/IExecutionContext.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Machete.Core 4 | { 5 | public interface IExecutionContext : IDisposable 6 | { 7 | ILexicalEnvironment LexicalEnviroment { get; set; } 8 | ILexicalEnvironment VariableEnviroment { get; set; } 9 | IDynamic ThisBinding { get; set; } 10 | bool Strict { get; set; } 11 | string CurrentFunction { get; set; } 12 | } 13 | } -------------------------------------------------------------------------------- /Machete.Runtime/NativeObjects/NUriError.cs: -------------------------------------------------------------------------------- 1 | using Machete.Core; 2 | using Machete.Runtime.RuntimeTypes.LanguageTypes; 3 | 4 | namespace Machete.Runtime.NativeObjects 5 | { 6 | public sealed class NUriError : LObject 7 | { 8 | public NUriError(IEnvironment environment) 9 | : base(environment) 10 | { 11 | Class = "Error"; 12 | Extensible = true; 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Machete.Tests/Statements/Block.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Xunit; 3 | 4 | namespace Machete.Tests 5 | { 6 | public class Block : TestBase 7 | { 8 | [Fact(DisplayName = "12.1 Block")] 9 | public void Test121A() 10 | { 11 | var script = @" 12 | { } 13 | "; 14 | Assert.Equal("undefined", (string)Engine.ExecuteScript(script)); 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /Machete.Runtime/NativeObjects/NEvalError.cs: -------------------------------------------------------------------------------- 1 | using Machete.Core; 2 | using Machete.Runtime.RuntimeTypes.LanguageTypes; 3 | 4 | namespace Machete.Runtime.NativeObjects 5 | { 6 | public sealed class NEvalError : LObject 7 | { 8 | public NEvalError(IEnvironment environment) 9 | : base(environment) 10 | { 11 | Class = "Error"; 12 | Extensible = true; 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Machete.Runtime/NativeObjects/NRangeError.cs: -------------------------------------------------------------------------------- 1 | using Machete.Core; 2 | using Machete.Runtime.RuntimeTypes.LanguageTypes; 3 | 4 | namespace Machete.Runtime.NativeObjects 5 | { 6 | public sealed class NRangeError : LObject 7 | { 8 | public NRangeError(IEnvironment environment) 9 | : base(environment) 10 | { 11 | Class = "Error"; 12 | Extensible = true; 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Machete.Runtime/NativeObjects/NTypeError.cs: -------------------------------------------------------------------------------- 1 | using Machete.Core; 2 | using Machete.Runtime.RuntimeTypes.LanguageTypes; 3 | 4 | namespace Machete.Runtime.NativeObjects 5 | { 6 | public sealed class NTypeError : LObject 7 | { 8 | public NTypeError(IEnvironment environment) 9 | : base(environment) 10 | { 11 | Class = "Error"; 12 | Extensible = true; 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Machete.Runtime/NativeObjects/NSyntaxError.cs: -------------------------------------------------------------------------------- 1 | using Machete.Core; 2 | using Machete.Runtime.RuntimeTypes.LanguageTypes; 3 | 4 | namespace Machete.Runtime.NativeObjects 5 | { 6 | public sealed class NSyntaxError : LObject 7 | { 8 | public NSyntaxError(IEnvironment environment) 9 | : base(environment) 10 | { 11 | Class = "Error"; 12 | Extensible = true; 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Machete.RegExp/RegExp.fs: -------------------------------------------------------------------------------- 1 | namespace Machete.RegExp 2 | 3 | type RegExp (info:RegExpInfo) = 4 | let matcher = Parser.parse info 5 | 6 | new (patternText:string, flags:RegExpFlags) = 7 | RegExp (RegExpInfo (patternText, flags)) 8 | new (patternText:string, flags:string) = 9 | RegExp (RegExpInfo (patternText, flags)) 10 | 11 | member x.Info = info 12 | member x.Match (input:string, index:int) = matcher input index 13 | -------------------------------------------------------------------------------- /Machete.Runtime/NativeObjects/NBoolean.cs: -------------------------------------------------------------------------------- 1 | using Machete.Core; 2 | using Machete.Runtime.RuntimeTypes.LanguageTypes; 3 | 4 | namespace Machete.Runtime.NativeObjects 5 | { 6 | public sealed class NBoolean : LObject, IPrimitiveWrapper 7 | { 8 | public IDynamic PrimitiveValue { get; set; } 9 | 10 | public NBoolean(IEnvironment environment) 11 | : base(environment) 12 | { 13 | 14 | } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /Machete.Tests/Statements/DebuggerStatement.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Xunit; 3 | 4 | namespace Machete.Tests 5 | { 6 | public class DebuggerStatement : TestBase 7 | { 8 | [Fact(DisplayName = "12.15 The debugger statement")] 9 | public void Test1215() 10 | { 11 | const string script = @"debugger;"; 12 | Assert.Equal("undefined", (string)Engine.ExecuteScript(script)); 13 | } 14 | } 15 | } -------------------------------------------------------------------------------- /Machete.Runtime/NativeObjects/NReferenceError.cs: -------------------------------------------------------------------------------- 1 | using Machete.Core; 2 | using Machete.Runtime.RuntimeTypes.LanguageTypes; 3 | 4 | namespace Machete.Runtime.NativeObjects 5 | { 6 | public sealed class NReferenceError : LObject 7 | { 8 | public NReferenceError(IEnvironment environment) 9 | : base(environment) 10 | { 11 | Class = "Error"; 12 | Extensible = true; 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /Machete.Core/ILexicalEnvironment.cs: -------------------------------------------------------------------------------- 1 | namespace Machete.Core 2 | { 3 | public interface ILexicalEnvironment 4 | { 5 | IEnvironmentRecord Record { get; set; } 6 | ILexicalEnvironment Parent { get; set; } 7 | 8 | IReference GetIdentifierReference(string name, bool strict); 9 | ILexicalEnvironment NewDeclarativeEnvironment(); 10 | ILexicalEnvironment NewObjectEnvironment(IObject bindingObject, bool provideThis); 11 | } 12 | } -------------------------------------------------------------------------------- /Machete.Core/IEnvironmentRecord.cs: -------------------------------------------------------------------------------- 1 | namespace Machete.Core 2 | { 3 | public interface IEnvironmentRecord : IReferenceBase 4 | { 5 | bool HasBinding(string name); 6 | void CreateMutableBinding(string name, bool deletable); 7 | void SetMutableBinding(string name, IDynamic value, bool strict); 8 | IDynamic GetBindingValue(string name, bool strict); 9 | bool DeleteBinding(string name); 10 | IDynamic ImplicitThisValue(); 11 | } 12 | } -------------------------------------------------------------------------------- /Machete.RegExp/Interpreter.fs: -------------------------------------------------------------------------------- 1 | namespace Machete.RegExp 2 | 3 | module Interpreter = 4 | 5 | let execute (info:RegExpInfo) (input:string) (index:int) = 6 | let root = TreeNode 7 | let rec execute node = 8 | match node with 9 | | Pattern (captureCount, disjunction) -> () 10 | | Disjunction (alternative, disjunction) -> () 11 | | Alternative (term, alternative) -> () 12 | | Term term -> () 13 | 14 | () 15 | 16 | -------------------------------------------------------------------------------- /Machete.Tests/Statements/ThrowStatement.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Xunit; 3 | using Machete.Core; 4 | 5 | namespace Machete.Tests 6 | { 7 | public class ThrowStatement : TestBase 8 | { 9 | [Fact(DisplayName = "12.13 The throw Statement")] 10 | public void Test1213() 11 | { 12 | var script = @" 13 | throw 'Error'; 14 | "; 15 | Assert.IsAssignableFrom(Engine.ExecuteScript(script)); 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /Machete.Parser/InputElement.fs: -------------------------------------------------------------------------------- 1 | namespace Machete.Parser 2 | 3 | type InputElement = 4 | | WhiteSpace of char * ElementData 5 | | LineTerminator of char * ElementData 6 | | MultiLineComment of string * bool * ElementData 7 | | SingleLineComment of string * ElementData 8 | | IdentifierName of string * ElementData 9 | | NullLiteral of ElementData 10 | | BooleanLiteral of bool * ElementData 11 | | NumericLiteral of double * ElementData 12 | | StringLiteral of string * ElementData 13 | | RegularExpressionLiteral of string * string * ElementData -------------------------------------------------------------------------------- /Machete.Runtime/NativeObjects/NArguments.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using Machete.Runtime.RuntimeTypes.LanguageTypes; 6 | using Machete.Core; 7 | 8 | namespace Machete.Runtime.NativeObjects 9 | { 10 | public sealed class NArguments : LObject 11 | { 12 | public IObject ParameterMap { get; set; } 13 | 14 | public NArguments(IEnvironment environment) 15 | : base(environment) 16 | { 17 | 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Machete.Core/Generators/Generator.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Machete.Core.Generators 4 | { 5 | public sealed class Generator 6 | { 7 | public Queue Steps { get; private set; } 8 | public IDynamic Current { get; set; } 9 | public bool Complete { get; set; } 10 | public bool Initialized { get; set; } 11 | 12 | public Generator(IEnumerable steps) 13 | { 14 | Steps = new Queue(steps); 15 | } 16 | } 17 | } -------------------------------------------------------------------------------- /Machete.Runtime/NativeObjects/NNumber.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using Machete.Runtime.RuntimeTypes.LanguageTypes; 6 | using Machete.Core; 7 | 8 | namespace Machete.Runtime.NativeObjects 9 | { 10 | public sealed class NNumber : LObject, IPrimitiveWrapper 11 | { 12 | public IDynamic PrimitiveValue { get; set; } 13 | 14 | public NNumber(IEnvironment environment) 15 | : base(environment) 16 | { 17 | 18 | } 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /Machete.Core/IFunction.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Machete.Core 4 | { 5 | public interface IFunction : IObject, ICallable, IConstructable, IHasInstance 6 | { 7 | ILexicalEnvironment Scope { get; set; } 8 | ReadOnlyList FormalParameterList { get; set; } 9 | Lazy Code { get; set; } 10 | IObject TargetFunction { get; set; } 11 | IDynamic BoundThis { get; set; } 12 | IArgs BoundArguments { get; set; } 13 | bool Strict { get; set; } 14 | bool BindFunction { get; set; } 15 | } 16 | } -------------------------------------------------------------------------------- /Machete.Core/MacheteRuntimeException.cs: -------------------------------------------------------------------------------- 1 | namespace Machete.Core 2 | { 3 | public class MacheteRuntimeException : MacheteException 4 | { 5 | public IDynamic Thrown { get; private set; } 6 | 7 | public override string Message 8 | { 9 | get { return Thrown.ToString(); } 10 | } 11 | 12 | public MacheteRuntimeException(IDynamic thrown) 13 | { 14 | Thrown = thrown; 15 | } 16 | 17 | 18 | public override string ToString() 19 | { 20 | return Thrown.ToString(); 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /Machete.Runtime/NativeObjects/NRegExp.cs: -------------------------------------------------------------------------------- 1 | using Machete.Core; 2 | using Machete.Runtime.RuntimeTypes.LanguageTypes; 3 | using RegExpMatcher = Machete.Compiler.RegExpParser.RegExpMatcher; 4 | 5 | namespace Machete.Runtime.NativeObjects 6 | { 7 | public sealed class NRegExp : LObject 8 | { 9 | public RegExpMatcher RegExpMatcher { get; set; } 10 | public string Body { get; set; } 11 | public string Flags { get; set; } 12 | 13 | 14 | public NRegExp(IEnvironment environment) 15 | : base(environment) 16 | { 17 | 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /Machete.RegExp/MatchState.fs: -------------------------------------------------------------------------------- 1 | namespace Machete.RegExp 2 | 3 | type MatchState = { 4 | RegExpInfo:RegExpInfo 5 | Captures:Captures 6 | Input:string 7 | StartIndex:int 8 | EndIndex:int 9 | } with 10 | member x.StartOfInput = 11 | x.EndIndex = 0 12 | member x.EndOfInput = 13 | x.EndIndex = x.Input.Length 14 | member x.Current = 15 | x.Input.[x.EndIndex] 16 | member x.Next = 17 | { x with EndIndex = x.EndIndex + 1 } 18 | member x.NextIf condition = 19 | if condition 20 | then { x with EndIndex = x.EndIndex + 1 } 21 | else x 22 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | #OS junk files 2 | [Tt]humbs.db 3 | *.DS_Store 4 | 5 | #Visual Studio files 6 | *.[Oo]bj 7 | *.exe 8 | *.pdb 9 | *.user 10 | *.aps 11 | *.pch 12 | *.vspscc 13 | *.vssscc 14 | *_i.c 15 | *_p.c 16 | *.ncb 17 | *.suo 18 | *.tlb 19 | *.tlh 20 | *.bak 21 | *.[Cc]ache 22 | *.ilk 23 | *.log 24 | *.lib 25 | *.sbr 26 | *.sdf 27 | ipch/ 28 | obj/ 29 | [Bb]in 30 | [Dd]ebug*/ 31 | [Rr]elease*/ 32 | Ankh.NoLoad 33 | 34 | #Tooling 35 | _ReSharper*/ 36 | *.resharper 37 | [Tt]est[Rr]esult* 38 | 39 | #Project files 40 | [Bb]uild/ 41 | 42 | #Subversion files 43 | .svn 44 | 45 | # Office Temp Files 46 | ~$* 47 | 48 | .vs/ 49 | packages/ -------------------------------------------------------------------------------- /Machete.Tests/Expressions/BinaryLogicalOperators.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Xunit; 3 | 4 | namespace Machete.Tests 5 | { 6 | public class BinaryLogicalOperators : TestBase 7 | { 8 | [Fact(DisplayName = "11.11 Binary Logical Operators - AND")] 9 | public void Test1111AND() 10 | { 11 | Assert.False((bool)Engine.ExecuteScript("false && true")); 12 | } 13 | 14 | [Fact(DisplayName = "11.11 Binary Logical Operators - OR")] 15 | public void Test1111OR() 16 | { 17 | Assert.True((bool)Engine.ExecuteScript("false || true")); 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /Machete.Tests/Expressions/PostfixExpressions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Xunit; 3 | 4 | namespace Machete.Tests 5 | { 6 | public class PostfixExpressions : TestBase 7 | { 8 | [Fact(DisplayName = "11.3.1 Postfix Increment Operator")] 9 | public void Test1131() 10 | { 11 | Assert.Equal(3.0, (double)Engine.ExecuteScript("var x = 1; x++ + x;")); 12 | } 13 | 14 | [Fact(DisplayName = "11.3.2 Postfix Decrement Operator")] 15 | public void Test1132() 16 | { 17 | Assert.Equal(5.0, (double)Engine.ExecuteScript("var x = 3; x-- + x;")); 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /Machete.Core/IPropertyDescriptor.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Machete.Core 4 | { 5 | public interface IPropertyDescriptor : IEquatable 6 | { 7 | IDynamic Value { get; set; } 8 | bool? Writable { get; set; } 9 | IDynamic Get { get; set; } 10 | IDynamic Set { get; set; } 11 | bool? Enumerable { get; set; } 12 | bool? Configurable { get; set; } 13 | bool IsAccessorDescriptor { get; } 14 | bool IsDataDescriptor { get; } 15 | bool IsGenericDescriptor { get; } 16 | bool IsEmpty { get; } 17 | 18 | IPropertyDescriptor Copy(); 19 | } 20 | } -------------------------------------------------------------------------------- /Machete.Core/BuiltinFunctionAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Machete.Core 4 | { 5 | [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)] 6 | public sealed class BuiltinFunctionAttribute : Attribute 7 | { 8 | public string Identifier { get; private set; } 9 | public ReadOnlyList FormalParameterList { get; private set; } 10 | 11 | public BuiltinFunctionAttribute(string identifier, params string[] formalParameterList) 12 | { 13 | Identifier = identifier; 14 | FormalParameterList = new ReadOnlyList(formalParameterList); 15 | } 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Machete.Core/FunctionDeclaration.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Machete.Core 4 | { 5 | public sealed class FunctionDeclaration 6 | { 7 | public string Identifier { get; private set; } 8 | public ReadOnlyList FormalParameterList { get; private set; } 9 | public ExecutableCode ExecutableCode { get; private set; } 10 | 11 | public FunctionDeclaration(string identifier, ReadOnlyList formalParameterList, ExecutableCode executableCode) 12 | { 13 | Identifier = identifier; 14 | FormalParameterList = formalParameterList; 15 | ExecutableCode = executableCode; 16 | } 17 | } 18 | } -------------------------------------------------------------------------------- /README.markdown: -------------------------------------------------------------------------------- 1 | # License 2 | 3 | Machete by Matthew O'Brien is licensed under a Creative Commons Attribution 3.0 Unported License. 4 | 5 | # Dependencies 6 | 7 | [.NET 4](http://www.microsoft.com/downloads/en/details.aspx?displaylang=en&FamilyID=0a391abd-25c1-4fc0-919f-b21f31ab88b7) 8 | 9 | [FParsec](https://bitbucket.org/fparsec/main/overview) 10 | 11 | [xUnit.net](http://xunit.codeplex.com/) -------------------------------------------------------------------------------- /Machete.Compiler/FloatParser.fs: -------------------------------------------------------------------------------- 1 | namespace Machete.Compiler 2 | 3 | open System 4 | 5 | module FloatParser = 6 | 7 | open FParsec.CharParsers 8 | open FParsec.Primitives 9 | 10 | let private floatParser replay = 11 | (parse { 12 | do! optional StringNumericLiteral.parseStrWhiteSpace 13 | let! result = StringNumericLiteral.parseStrDecimalLiteral 14 | return result 15 | }) replay 16 | 17 | let Parse (text:string) = 18 | let result = run floatParser text 19 | match result with 20 | | Success (value, _, _) -> 21 | StringNumericLiteral.evalStrDecimalLiteral value 22 | | _ -> Double.NaN -------------------------------------------------------------------------------- /Machete.Tests/Expressions/AdditiveOperators.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Xunit; 3 | 4 | namespace Machete.Tests 5 | { 6 | public class AdditiveOperators : TestBase 7 | { 8 | [Fact(DisplayName = "11.6.1 The Addition operator ( + )")] 9 | public void Test1161() 10 | { 11 | Assert.Equal("1A", (string)Engine.ExecuteScript("1 + 'A'")); 12 | Assert.Equal(2.0, (double)Engine.ExecuteScript("1 + 1")); 13 | } 14 | 15 | [Fact(DisplayName = "11.6.2 The Subtraction Operator ( - )")] 16 | public void Test1162() 17 | { 18 | Assert.Equal(0.0, (double)Engine.ExecuteScript("1 - 1")); 19 | } 20 | } 21 | } -------------------------------------------------------------------------------- /Machete.Runtime/NativeObjects/NDate.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using Machete.Runtime.RuntimeTypes.LanguageTypes; 6 | using Machete.Core; 7 | 8 | namespace Machete.Runtime.NativeObjects 9 | { 10 | public sealed class NDate : LObject, IPrimitiveWrapper 11 | { 12 | public IDynamic PrimitiveValue { get; set; } 13 | 14 | public NDate(IEnvironment environment) 15 | : base(environment) 16 | { 17 | 18 | } 19 | 20 | public override IDynamic DefaultValue(string hint) 21 | { 22 | return base.DefaultValue(hint ?? "String"); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /Machete.Core/MacheteException.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.Serialization; 3 | 4 | namespace Machete.Core 5 | { 6 | public class MacheteException : Exception 7 | { 8 | public MacheteException() 9 | { 10 | 11 | } 12 | 13 | public MacheteException(string message) 14 | : base(message) 15 | { 16 | 17 | } 18 | 19 | public MacheteException(string message, Exception innerException) 20 | : base(message, innerException) 21 | { 22 | 23 | } 24 | 25 | public MacheteException(SerializationInfo info, StreamingContext context) 26 | : base(info, context) 27 | { 28 | 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /Machete.Tests/Statements/SwitchStatement.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Xunit; 3 | 4 | namespace Machete.Tests 5 | { 6 | public class SwitchStatement : TestBase 7 | { 8 | [Fact(DisplayName = "12.11 The switch Statement")] 9 | public void Test129A() 10 | { 11 | var script = @" 12 | var n = 1; 13 | switch (n) { 14 | case 1: 15 | return true; 16 | default: 17 | return false; 18 | } 19 | "; 20 | Assert.True((bool)Engine.ExecuteScript(script)); 21 | Assert.True((bool)Engine.ExecuteScript("delete n;")); 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /Machete.RegExp/RegExpTree.fs: -------------------------------------------------------------------------------- 1 | namespace Machete.RegExp 2 | 3 | type RegExpTree = 4 | | TreeNode 5 | | Pattern of int * RegExpTree 6 | | Disjunction of RegExpTree * RegExpTree option 7 | | Alternative of RegExpTree * RegExpTree option 8 | | Term of Term 9 | 10 | and Term = 11 | | Assertion of Assertion 12 | | Atom of Atom * Quantifier option 13 | 14 | and Assertion = 15 | | StartOfInput 16 | | EndOfInput 17 | | WordBoundary 18 | | NonWordBoundary 19 | | FollowedBy of RegExpTree 20 | | NotFollowedBy of RegExpTree 21 | 22 | and Quantifier = { 23 | min:int 24 | max:Limit 25 | greedy:bool 26 | } 27 | 28 | and Atom = 29 | | Character of char 30 | | Characters of char seq 31 | | WildCard 32 | | CapturingGroup of int * RegExpTree 33 | | NonCapturingGroup of RegExpTree 34 | -------------------------------------------------------------------------------- /Machete.Runtime/HostObjects/Iterables/HMapIterable.cs: -------------------------------------------------------------------------------- 1 | using Machete.Core; 2 | 3 | namespace Machete.Runtime.HostObjects.Iterables 4 | { 5 | public sealed class HMapIterable : HIterableBase 6 | { 7 | private readonly IObject _iterable; 8 | private readonly ICallable _mapping; 9 | 10 | public HMapIterable(IEnvironment environment, IObject iterable, ICallable mapping) 11 | : base(environment) 12 | { 13 | _iterable = iterable; 14 | _mapping = mapping; 15 | } 16 | 17 | public override IDynamic CreateIterator(IEnvironment environment, IArgs args) 18 | { 19 | var iterator = new Iterator(environment, _iterable); 20 | return new HMapIterator(environment, iterator, _mapping); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /Machete.Tests/Expressions/MultiplicativeOperators.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Xunit; 3 | 4 | namespace Machete.Tests 5 | { 6 | public class MultiplicativeOperators : TestBase 7 | { 8 | [Fact(DisplayName = "11.5.1 Applying the * Operator")] 9 | public void Test1151() 10 | { 11 | Assert.Equal(2.0, (double)Engine.ExecuteScript("1 * 2")); 12 | } 13 | 14 | [Fact(DisplayName = "11.5.2 Applying the / Operator")] 15 | public void Test1152() 16 | { 17 | Assert.Equal(0.5, (double)Engine.ExecuteScript("1 / 2")); 18 | } 19 | 20 | [Fact(DisplayName = "11.5.3 Applying the % Operator")] 21 | public void Test1153() 22 | { 23 | Assert.Equal(0.0, (double)Engine.ExecuteScript("10 % 2")); 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /Machete.Interactive/AssemblyInfo.fs: -------------------------------------------------------------------------------- 1 | namespace Machete.Interactive 2 | 3 | open System.Reflection 4 | open System.Runtime.InteropServices 5 | 6 | module internal AssemblyInfo = 7 | let [] Version = "0.1.2.0652" 8 | 9 | [] 10 | [] 11 | [] 12 | [] 13 | [] 14 | [] 15 | [] 16 | [] 17 | [] 18 | [] 19 | [] 20 | () -------------------------------------------------------------------------------- /Machete.Core/IObject.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | 3 | namespace Machete.Core 4 | { 5 | public interface IObject : IDynamic, IReferenceBase, IEnumerable 6 | { 7 | IObject Prototype { get; set; } 8 | string Class { get; set; } 9 | bool Extensible { get; set; } 10 | 11 | IPropertyDescriptor GetOwnProperty(string name); 12 | IPropertyDescriptor GetProperty(string name); 13 | IDynamic Get(string name); 14 | void Put(string name, IDynamic value, bool strict); 15 | bool CanPut(string name); 16 | bool HasProperty(string name); 17 | bool Delete(string name, bool strict); 18 | IDynamic DefaultValue(string hint); 19 | bool DefineOwnProperty(string name, IPropertyDescriptor value, bool strict); 20 | 21 | void Initialize(); 22 | } 23 | } -------------------------------------------------------------------------------- /Machete.Tests/Expressions/BinaryBitwiseOperators.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Xunit; 3 | 4 | namespace Machete.Tests 5 | { 6 | public class BinaryBitwiseOperators : TestBase 7 | { 8 | [Fact(DisplayName = "11.10 Binary Bitwise Operators - AND")] 9 | public void Test1110AND() 10 | { 11 | Assert.Equal(10 & 2, (double)Engine.ExecuteScript("10 & 2")); 12 | } 13 | 14 | [Fact(DisplayName = "11.10 Binary Bitwise Operators - XOR")] 15 | public void Test1110XOR() 16 | { 17 | Assert.Equal(10 ^ 2, (double)Engine.ExecuteScript("10 ^ 2")); 18 | } 19 | 20 | [Fact(DisplayName = "11.10 Binary Bitwise Operators - OR")] 21 | public void Test1110OR() 22 | { 23 | Assert.Equal(10 | 2, (double)Engine.ExecuteScript("10 | 2")); 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /Machete.Tests/Lexical Conventions/Comments.cs: -------------------------------------------------------------------------------- 1 | using Machete.Core; 2 | using Xunit; 3 | 4 | namespace Machete.Tests.Lexical_Conventions 5 | { 6 | public sealed class Comments : TestBase 7 | { 8 | [Fact(DisplayName = "07.04 Comments: SingleLineComment")] 9 | public void Test0704A() 10 | { 11 | var r = Engine.ExecuteScriptToDynamic("//A single line comment\n2"); 12 | Assert.IsAssignableFrom(r); 13 | Assert.Equal(2.0, ((INumber)r).BaseValue); 14 | } 15 | 16 | [Fact(DisplayName = "07.04 Comments: MultiLineComment")] 17 | public void Test0704B() 18 | { 19 | var r = Engine.ExecuteScriptToDynamic("/*A multi \n line comment*/\n2"); 20 | Assert.IsAssignableFrom(r); 21 | Assert.Equal(2.0, ((INumber)r).BaseValue); 22 | } 23 | } 24 | } -------------------------------------------------------------------------------- /Machete.Runtime/NativeObjects/BuiltinObjects/PUriError.cs: -------------------------------------------------------------------------------- 1 | using Machete.Core; 2 | using Machete.Runtime.RuntimeTypes.LanguageTypes; 3 | 4 | namespace Machete.Runtime.NativeObjects.BuiltinObjects.PrototypeObjects 5 | { 6 | public sealed class PUriError : LObject 7 | { 8 | public PUriError(IEnvironment environment) 9 | : base(environment) 10 | { 11 | 12 | } 13 | 14 | public override void Initialize() 15 | { 16 | Class = "Error"; 17 | Extensible = true; 18 | Prototype = Environment.ErrorPrototype; 19 | DefineOwnProperty("name", Environment.CreateDataDescriptor(Environment.CreateString("URIError"), true, false, true), false); 20 | DefineOwnProperty("message", Environment.CreateDataDescriptor(Environment.CreateString(""), true, false, true), false); 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /Machete.Runtime/NativeObjects/BuiltinObjects/PEvalError.cs: -------------------------------------------------------------------------------- 1 | using Machete.Core; 2 | using Machete.Runtime.RuntimeTypes.LanguageTypes; 3 | 4 | namespace Machete.Runtime.NativeObjects.BuiltinObjects.PrototypeObjects 5 | { 6 | public sealed class PEvalError : LObject 7 | { 8 | public PEvalError(IEnvironment environment) 9 | : base(environment) 10 | { 11 | 12 | } 13 | 14 | public override void Initialize() 15 | { 16 | Class = "Error"; 17 | Extensible = true; 18 | Prototype = Environment.ErrorPrototype; 19 | DefineOwnProperty("name", Environment.CreateDataDescriptor(Environment.CreateString("EvalError"), true, false, true), false); 20 | DefineOwnProperty("message", Environment.CreateDataDescriptor(Environment.CreateString(""), true, false, true), false); 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /Machete.Runtime/NativeObjects/BuiltinObjects/PTypeError.cs: -------------------------------------------------------------------------------- 1 | using Machete.Core; 2 | using Machete.Runtime.RuntimeTypes.LanguageTypes; 3 | 4 | namespace Machete.Runtime.NativeObjects.BuiltinObjects.PrototypeObjects 5 | { 6 | public sealed class PTypeError : LObject 7 | { 8 | public PTypeError(IEnvironment environment) 9 | : base(environment) 10 | { 11 | 12 | } 13 | 14 | public override void Initialize() 15 | { 16 | Class = "Error"; 17 | Extensible = true; 18 | Prototype = Environment.ErrorPrototype; 19 | DefineOwnProperty("name", Environment.CreateDataDescriptor(Environment.CreateString("TypeError"), true, false, true), false); 20 | DefineOwnProperty("message", Environment.CreateDataDescriptor(Environment.CreateString(""), true, false, true), false); 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /Machete.Runtime/NativeObjects/BuiltinObjects/PRangeError.cs: -------------------------------------------------------------------------------- 1 | using Machete.Core; 2 | using Machete.Runtime.RuntimeTypes.LanguageTypes; 3 | 4 | namespace Machete.Runtime.NativeObjects.BuiltinObjects.PrototypeObjects 5 | { 6 | public sealed class PRangeError : LObject 7 | { 8 | public PRangeError(IEnvironment environment) 9 | : base(environment) 10 | { 11 | 12 | } 13 | 14 | public override void Initialize() 15 | { 16 | Class = "Error"; 17 | Extensible = true; 18 | Prototype = Environment.ErrorPrototype; 19 | DefineOwnProperty("name", Environment.CreateDataDescriptor(Environment.CreateString("RangeError"), true, false, true), false); 20 | DefineOwnProperty("message", Environment.CreateDataDescriptor(Environment.CreateString(""), true, false, true), false); 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /Machete.Tests/Expressions/BitwiseShiftOperators.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Xunit; 3 | 4 | namespace Machete.Tests 5 | { 6 | public class BitwiseShiftOperators : TestBase 7 | { 8 | [Fact(DisplayName = "11.7.1 The Left Shift Operator ( << )")] 9 | public void Test1171() 10 | { 11 | Assert.Equal(16.0, (double)Engine.ExecuteScript("4 << 2")); 12 | } 13 | 14 | [Fact(DisplayName = "11.7.2 The Signed Right Shift Operator ( >> )")] 15 | public void Test1172() 16 | { 17 | Assert.Equal(-536870912.0, (double)Engine.ExecuteScript("2147483648 >> 2")); 18 | } 19 | 20 | [Fact(DisplayName = "11.7.3 The Unsigned Right Shift Operator ( >>> )")] 21 | public void Test1173() 22 | { 23 | Assert.Equal(536870912.0, (double)Engine.ExecuteScript("2147483648 >>> 2")); 24 | } 25 | } 26 | } -------------------------------------------------------------------------------- /Machete.Runtime/NativeObjects/BuiltinObjects/PSyntaxError.cs: -------------------------------------------------------------------------------- 1 | using Machete.Core; 2 | using Machete.Runtime.RuntimeTypes.LanguageTypes; 3 | 4 | namespace Machete.Runtime.NativeObjects.BuiltinObjects.PrototypeObjects 5 | { 6 | public sealed class PSyntaxError : LObject 7 | { 8 | public PSyntaxError(IEnvironment environment) 9 | : base(environment) 10 | { 11 | 12 | } 13 | 14 | public override void Initialize() 15 | { 16 | Class = "Error"; 17 | Extensible = true; 18 | Prototype = Environment.ErrorPrototype; 19 | DefineOwnProperty("name", Environment.CreateDataDescriptor(Environment.CreateString("SyntaxError"), true, false, true), false); 20 | DefineOwnProperty("message", Environment.CreateDataDescriptor(Environment.CreateString(""), true, false, true), false); 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /Machete.Core/ExecutableCode.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace Machete.Core 7 | { 8 | public sealed class ExecutableCode 9 | { 10 | public readonly Code Code; 11 | public readonly ReadOnlyList VariableDeclarations; 12 | public readonly ReadOnlyList FunctionDeclarations; 13 | public readonly bool Strict; 14 | 15 | public ExecutableCode( 16 | Code code, 17 | ReadOnlyList variableDeclarations, 18 | ReadOnlyList functionDeclarations, 19 | bool strict) 20 | { 21 | Code = code; 22 | VariableDeclarations = variableDeclarations; 23 | FunctionDeclarations = functionDeclarations; 24 | Strict = strict; 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /Machete.Runtime/NativeObjects/BuiltinObjects/PReferenceError.cs: -------------------------------------------------------------------------------- 1 | using Machete.Core; 2 | using Machete.Runtime.RuntimeTypes.LanguageTypes; 3 | 4 | namespace Machete.Runtime.NativeObjects.BuiltinObjects.PrototypeObjects 5 | { 6 | public sealed class PReferenceError : LObject 7 | { 8 | public PReferenceError(IEnvironment environment) 9 | : base(environment) 10 | { 11 | 12 | } 13 | 14 | public override void Initialize() 15 | { 16 | Class = "Error"; 17 | Extensible = true; 18 | Prototype = Environment.ErrorPrototype; 19 | DefineOwnProperty("name", Environment.CreateDataDescriptor(Environment.CreateString("ReferenceError"), true, false, true), false); 20 | DefineOwnProperty("message", Environment.CreateDataDescriptor(Environment.CreateString(""), true, false, true), false); 21 | } 22 | } 23 | } -------------------------------------------------------------------------------- /Machete/AssemblyInfo.fs: -------------------------------------------------------------------------------- 1 | namespace Machete 2 | 3 | open System.Reflection 4 | open System.Runtime.InteropServices 5 | 6 | [] 7 | [] 8 | [] 9 | [] 10 | [] 11 | [] 12 | [] 13 | [] 14 | [] 15 | [] 16 | [] 17 | [] 18 | () -------------------------------------------------------------------------------- /Machete.Runtime/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | [assembly: AssemblyTitle("Machete.Runtime")] 6 | [assembly: AssemblyDescription(Machete.Core.AssemblyInfo.Description)] 7 | [assembly: AssemblyConfiguration(Machete.Core.AssemblyInfo.Configuration)] 8 | [assembly: AssemblyCompany(Machete.Core.AssemblyInfo.Company)] 9 | [assembly: AssemblyProduct(Machete.Core.AssemblyInfo.Product)] 10 | [assembly: AssemblyCopyright(Machete.Core.AssemblyInfo.Copyright)] 11 | [assembly: AssemblyTrademark(Machete.Core.AssemblyInfo.Trademark)] 12 | [assembly: AssemblyCulture(Machete.Core.AssemblyInfo.Culture)] 13 | [assembly: ComVisible(false)] 14 | [assembly: Guid("5a219f6b-0c77-4d01-8ba4-7b825b498de0")] 15 | [assembly: AssemblyVersion(Machete.Core.AssemblyInfo.Version)] 16 | [assembly: AssemblyFileVersion(Machete.Core.AssemblyInfo.Version)] -------------------------------------------------------------------------------- /Machete.Tests/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | [assembly: AssemblyTitle("Machete.Tests")] 6 | [assembly: AssemblyDescription(Machete.Core.AssemblyInfo.Description)] 7 | [assembly: AssemblyConfiguration(Machete.Core.AssemblyInfo.Configuration)] 8 | [assembly: AssemblyCompany(Machete.Core.AssemblyInfo.Company)] 9 | [assembly: AssemblyProduct(Machete.Core.AssemblyInfo.Product)] 10 | [assembly: AssemblyCopyright(Machete.Core.AssemblyInfo.Copyright)] 11 | [assembly: AssemblyTrademark(Machete.Core.AssemblyInfo.Trademark)] 12 | [assembly: AssemblyCulture(Machete.Core.AssemblyInfo.Culture)] 13 | [assembly: ComVisible(false)] 14 | [assembly: Guid("21446d07-768d-4860-8089-e405c74e3cb0")] 15 | [assembly: AssemblyVersion(Machete.Core.AssemblyInfo.Version)] 16 | [assembly: AssemblyFileVersion(Machete.Core.AssemblyInfo.Version)] 17 | -------------------------------------------------------------------------------- /Machete.Core/Output.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Concurrent; 3 | 4 | namespace Machete.Core 5 | { 6 | public sealed class Output : IDisposable 7 | { 8 | private readonly BlockingCollection _messages = new BlockingCollection(); 9 | 10 | public void Write(string value) 11 | { 12 | _messages.TryAdd(value ?? string.Empty); 13 | } 14 | 15 | public string Take() 16 | { 17 | return _messages.Take(); 18 | } 19 | 20 | public bool TryTake(out string result) 21 | { 22 | return _messages.TryTake(out result); 23 | } 24 | 25 | public bool TryTake(out string result, int timeout) 26 | { 27 | return _messages.TryTake(out result, timeout); 28 | } 29 | 30 | public void Dispose() 31 | { 32 | _messages.Dispose(); 33 | } 34 | } 35 | } -------------------------------------------------------------------------------- /Machete.Compiler/AssemblyInfo.fs: -------------------------------------------------------------------------------- 1 | namespace Machete.Compiler 2 | 3 | open System.Reflection 4 | open System.Runtime.InteropServices 5 | 6 | [] 7 | [] 8 | [] 9 | [] 10 | [] 11 | [] 12 | [] 13 | [] 14 | [] 15 | [] 16 | [] 17 | [] 18 | () 19 | 20 | -------------------------------------------------------------------------------- /Machete.RegExp/Captures.fs: -------------------------------------------------------------------------------- 1 | namespace Machete.RegExp 2 | 3 | open System.Collections 4 | open System.Collections.Generic 5 | 6 | type Captures = 7 | 8 | val captures : List 9 | 10 | new (cs:string seq) = { 11 | captures = List (cs) 12 | } 13 | 14 | private new (cs:List) = { 15 | captures = cs 16 | } 17 | 18 | member x.Length = x.captures.Count 19 | 20 | member x.Item index = x.captures.[index] 21 | 22 | member x.CopyWith (index:int, value:string) = 23 | let cs = x.captures.ToArray () 24 | cs.[index] <- value 25 | Captures cs 26 | 27 | interface IEnumerable with 28 | member x.GetEnumerator () : IEnumerator = 29 | x.captures.GetEnumerator () :> IEnumerator 30 | interface IEnumerable with 31 | member x.GetEnumerator () : IEnumerator = 32 | x.captures.GetEnumerator () :> IEnumerator 33 | -------------------------------------------------------------------------------- /Machete.Runtime/ExecutionContext.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using Machete.Runtime.RuntimeTypes.LanguageTypes; 6 | using Machete.Runtime.RuntimeTypes.SpecificationTypes; 7 | using System.Reflection; 8 | using Machete.Core; 9 | 10 | namespace Machete.Runtime 11 | { 12 | public sealed class ExecutionContext : IExecutionContext 13 | { 14 | private readonly Action _dispose; 15 | 16 | public string CurrentFunction { get; set; } 17 | public bool Strict { get; set; } 18 | public ILexicalEnvironment LexicalEnviroment { get; set; } 19 | public ILexicalEnvironment VariableEnviroment { get; set; } 20 | public IDynamic ThisBinding { get; set; } 21 | 22 | public ExecutionContext(Action dispose) 23 | { 24 | _dispose = dispose; 25 | } 26 | 27 | public void Dispose() 28 | { 29 | _dispose(); 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /Machete.Tests/Statements/ReturnStatement.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Xunit; 3 | 4 | namespace Machete.Tests 5 | { 6 | public class ReturnStatement : TestBase 7 | { 8 | [Fact(DisplayName = "12.9 The return Statement -> With Expression")] 9 | public void Test129A() 10 | { 11 | var script = @" 12 | function test() { 13 | return 2; 14 | } 15 | return test(); 16 | "; 17 | Assert.Equal(2.0, (double)Engine.ExecuteScript(script)); 18 | } 19 | 20 | [Fact(DisplayName = "12.9 The return Statement -> With No Expression")] 21 | public void Test129B() 22 | { 23 | var script = @" 24 | function test() { 25 | return; 26 | } 27 | typeof test(); 28 | "; 29 | Assert.Equal("undefined", (string)Engine.ExecuteScript(script)); 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /Machete.Core/DataDescriptorAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace Machete.Core 4 | { 5 | [AttributeUsage(AttributeTargets.Method, AllowMultiple = false, Inherited = false)] 6 | public sealed class DataDescriptorAttribute : Attribute 7 | { 8 | public bool? Writable { get; private set; } 9 | public bool? Enumerable { get; private set; } 10 | public bool? Configurable { get; private set; } 11 | 12 | public DataDescriptorAttribute(bool writable) 13 | { 14 | Writable = writable; 15 | } 16 | 17 | public DataDescriptorAttribute(bool writable, bool enumerable) 18 | { 19 | Writable = writable; 20 | Enumerable = enumerable; 21 | } 22 | 23 | public DataDescriptorAttribute(bool writable, bool enumerable, bool configurable) 24 | { 25 | Writable = writable; 26 | Enumerable = enumerable; 27 | Configurable = configurable; 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /Machete.Tests/Statements/WithStatement.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Xunit; 3 | 4 | namespace Machete.Tests 5 | { 6 | public class WithStatement : TestBase 7 | { 8 | [Fact(DisplayName = "12.10 The with Statement -> with ( Expression ) Statement")] 9 | public void Test1210() 10 | { 11 | var script = @" 12 | var n = 'C', r = 'A'; 13 | with ({ n: 'B' }) { 14 | r += n; 15 | } 16 | return r + n; 17 | "; 18 | Assert.Equal("ABC", (string)Engine.ExecuteScript(script)); 19 | } 20 | 21 | [Fact(DisplayName = "12.10.1 Strict Mode Restrictions")] 22 | public void Test12101() 23 | { 24 | var script = @" 25 | 'use strict'; 26 | with (Object) { 27 | 28 | } 29 | "; 30 | var r = Engine.ExecuteScript(script); 31 | Assert.IsAssignableFrom(r); 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /Machete.Tests/Statements/IfStatement.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Xunit; 3 | 4 | namespace Machete.Tests 5 | { 6 | public class IfStatement : TestBase 7 | { 8 | [Fact(DisplayName = "12.5 The if Statement -> if ( Expression ) Statement else Statement")] 9 | public void Test125A() 10 | { 11 | var script = @" 12 | if (true) { 13 | return true; 14 | } else { 15 | return false; 16 | } 17 | "; 18 | Assert.True((bool)Engine.ExecuteScript(script)); 19 | } 20 | 21 | [Fact(DisplayName = "12.5 The if Statement -> if ( Expression ) Statement")] 22 | public void Test125B() 23 | { 24 | var script = @" 25 | var x = 999; 26 | if (false) { 27 | x += 1; 28 | } 29 | return x; 30 | "; 31 | Assert.Equal(999.0, (double)Engine.ExecuteScript(script)); 32 | } 33 | } 34 | } -------------------------------------------------------------------------------- /Machete.Runtime/HostObjects/Iterables/HFilterIterable.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using Machete.Runtime.RuntimeTypes.LanguageTypes; 6 | using Machete.Core; 7 | using Machete.Runtime.NativeObjects.BuiltinObjects; 8 | 9 | namespace Machete.Runtime.HostObjects.Iterables 10 | { 11 | public sealed class HFilterIterable : HIterableBase 12 | { 13 | private readonly IObject _iterable; 14 | private readonly ICallable _predicate; 15 | 16 | public HFilterIterable(IEnvironment environment, IObject iterable, ICallable predicate) 17 | : base(environment) 18 | { 19 | _iterable = iterable; 20 | _predicate = predicate; 21 | } 22 | 23 | public override IDynamic CreateIterator(IEnvironment environment, IArgs args) 24 | { 25 | var iterator = new Iterator(environment, _iterable); 26 | return new HFilterIterator(environment, iterator, _predicate); 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /Machete.Runtime/HostObjects/HOutput.cs: -------------------------------------------------------------------------------- 1 | using Machete.Core; 2 | using Machete.Runtime.RuntimeTypes.LanguageTypes; 3 | 4 | namespace Machete.Runtime.HostObjects 5 | { 6 | public sealed class HOutput : LObject 7 | { 8 | public HOutput(IEnvironment environment) 9 | : base(environment) 10 | { 11 | Initialize(); 12 | } 13 | 14 | public override void Initialize() 15 | { 16 | Class = "Output"; 17 | Prototype = null; 18 | Extensible = true; 19 | base.Initialize(); 20 | } 21 | 22 | public override IDynamic DefaultValue(string hint) 23 | { 24 | return Environment.CreateString("[object, Output]"); 25 | } 26 | 27 | [BuiltinFunction("write", "value"), DataDescriptor(false, false, false)] 28 | internal static IDynamic Write(IEnvironment environment, IArgs args) 29 | { 30 | var value = args[0].ConvertToString().BaseValue; 31 | environment.Output.Write(value); 32 | return environment.Undefined; 33 | } 34 | } 35 | } -------------------------------------------------------------------------------- /Machete.Core/Generators/GeneratorSteps.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Collections; 3 | using System.Linq; 4 | 5 | namespace Machete.Core.Generators 6 | { 7 | public sealed class GeneratorSteps : IEnumerable 8 | { 9 | private readonly Queue _queue; 10 | 11 | public int Count 12 | { 13 | get { return _queue.Count; } 14 | } 15 | 16 | public GeneratorSteps(IEnumerable items) 17 | { 18 | _queue = new Queue(items); 19 | } 20 | 21 | public GeneratorSteps(IEnumerable first, IEnumerable last) 22 | { 23 | _queue = new Queue(first.Concat(last)); 24 | } 25 | 26 | public GeneratorStep Next() 27 | { 28 | return _queue.Dequeue(); 29 | } 30 | 31 | public IEnumerator GetEnumerator() 32 | { 33 | return _queue.GetEnumerator(); 34 | } 35 | 36 | IEnumerator IEnumerable.GetEnumerator() 37 | { 38 | return _queue.GetEnumerator(); 39 | } 40 | } 41 | } -------------------------------------------------------------------------------- /Machete.Runtime/HostObjects/Iterables/HIterableBase.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using Machete.Runtime.RuntimeTypes.LanguageTypes; 6 | using Machete.Core; 7 | using Machete.Core.Generators; 8 | using Machete.Runtime.NativeObjects.BuiltinObjects; 9 | 10 | namespace Machete.Runtime.HostObjects.Iterables 11 | { 12 | public abstract class HIterableBase : LObject 13 | { 14 | public BFunction CreateIteratorBuiltinFunction { get; private set; } 15 | 16 | public HIterableBase(IEnvironment environment) 17 | : base(environment) 18 | { 19 | Class = "Iterable"; 20 | Extensible = true; 21 | Prototype = environment.ObjectPrototype; 22 | 23 | CreateIteratorBuiltinFunction = new BFunction(environment, CreateIterator, ReadOnlyList.Empty); 24 | 25 | new LObject.Builder(this) 26 | .SetAttributes(false, false, false) 27 | .AppendDataProperty("createIterator", CreateIteratorBuiltinFunction); 28 | } 29 | 30 | public abstract IDynamic CreateIterator(IEnvironment environment, IArgs args); 31 | } 32 | } -------------------------------------------------------------------------------- /Machete.RegExp/RegExpInfo.fs: -------------------------------------------------------------------------------- 1 | namespace Machete.RegExp 2 | 3 | type RegExpInfo (patternText:string, flags:RegExpFlags) = 4 | 5 | do 6 | if patternText = null then 7 | nullArg "patternText" 8 | 9 | new (patternText:string, flags:string) = 10 | if flags = null then 11 | nullArg "flags" 12 | let flags = 13 | match flags.Length with 14 | | 0 -> 15 | RegExpFlags.None 16 | | l when l > 3 -> 17 | invalidArg "flags" "Length cannot be greater than 3." 18 | | _ -> 19 | if flags.Contains("g") then RegExpFlags.Global else RegExpFlags.None 20 | ||| if flags.Contains("i") then RegExpFlags.IgnoreCase else RegExpFlags.None 21 | ||| if flags.Contains("m") then RegExpFlags.Multiline else RegExpFlags.None 22 | RegExpInfo (patternText, flags) 23 | 24 | member x.PatternText = patternText 25 | member x.Flags = flags 26 | member x.Global = flags ||| RegExpFlags.Global = RegExpFlags.Global 27 | member x.IgnoreCase = flags ||| RegExpFlags.IgnoreCase = RegExpFlags.IgnoreCase 28 | member x.Multiline = flags ||| RegExpFlags.Multiline = RegExpFlags.Multiline 29 | -------------------------------------------------------------------------------- /Machete.Tests/Statements/LabelledStatement.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Xunit; 3 | 4 | namespace Machete.Tests 5 | { 6 | public class LabelledStatement : TestBase 7 | { 8 | [Fact(DisplayName = "12.12 Labelled Statements -> break Label;")] 9 | public void Test1212A() 10 | { 11 | var script = @" 12 | var i = 0, b = true; 13 | Test: while (b) { 14 | while (++i < 10) { 15 | break Test; 16 | } 17 | b = false; 18 | } 19 | return i + b; 20 | "; 21 | Assert.Equal(2.0, (double)Engine.ExecuteScript(script)); 22 | } 23 | 24 | [Fact(DisplayName = "12.12 Labelled Statements -> continue Label;")] 25 | public void Test1212B() 26 | { 27 | var script = @" 28 | var i = 0; 29 | Test: while (++i < 10) { 30 | while (true) { 31 | continue Test; 32 | } 33 | } 34 | return i; 35 | "; 36 | Assert.Equal(10.0, (double)Engine.ExecuteScript(script)); 37 | } 38 | } 39 | } -------------------------------------------------------------------------------- /Machete.Runtime/NativeObjects/BuiltinObjects/BFunction.cs: -------------------------------------------------------------------------------- 1 | using Machete.Core; 2 | using Machete.Runtime.RuntimeTypes.LanguageTypes; 3 | 4 | namespace Machete.Runtime.NativeObjects.BuiltinObjects 5 | { 6 | public sealed class BFunction : LObject, ICallable 7 | { 8 | private readonly Code _code; 9 | private readonly ReadOnlyList _formalParameters; 10 | 11 | public BFunction(IEnvironment environment, Code code, ReadOnlyList formalParameters) 12 | : base (environment) 13 | { 14 | _code = code; 15 | _formalParameters = formalParameters; 16 | Class = "Function"; 17 | Extensible = true; 18 | Prototype = Environment.FunctionPrototype; 19 | DefineOwnProperty("length", Environment.CreateDataDescriptor(Environment.CreateNumber(_formalParameters.Count), false, false, false), false); 20 | } 21 | 22 | public IDynamic Call(IEnvironment environment, IDynamic thisBinding, IArgs args) 23 | { 24 | using (var newContext = environment.EnterContext()) 25 | { 26 | Environment.Context.ThisBinding = thisBinding; 27 | return _code(environment, args); 28 | } 29 | } 30 | } 31 | } -------------------------------------------------------------------------------- /Machete.Core/ReadOnlyList.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections; 3 | using System.Collections.Generic; 4 | using System.Diagnostics.Contracts; 5 | using System.Linq; 6 | 7 | namespace Machete.Core 8 | { 9 | public class ReadOnlyList : IEnumerable 10 | { 11 | private readonly T[] _items; 12 | public static readonly ReadOnlyList Empty = new ReadOnlyList(new T[0]); 13 | 14 | 15 | public ReadOnlyList(params T[] items) 16 | { 17 | _items = items; 18 | } 19 | 20 | public ReadOnlyList(IEnumerable items) 21 | { 22 | _items = items.ToArray(); 23 | } 24 | 25 | 26 | public T this[int index] 27 | { 28 | get 29 | { 30 | return _items[index]; 31 | } 32 | } 33 | 34 | public int Count 35 | { 36 | get 37 | { 38 | return _items.Length; 39 | } 40 | } 41 | 42 | 43 | public IEnumerator GetEnumerator() 44 | { 45 | return _items.Cast().GetEnumerator(); 46 | } 47 | 48 | IEnumerator IEnumerable.GetEnumerator() 49 | { 50 | return _items.Cast().GetEnumerator(); 51 | } 52 | } 53 | } -------------------------------------------------------------------------------- /Machete.Interactive/CommandParser.fs: -------------------------------------------------------------------------------- 1 | namespace Machete.Interactive 2 | 3 | module CommandParser = 4 | 5 | open FParsec 6 | open FParsec.CharParsers 7 | open FParsec.Primitives 8 | 9 | 10 | let private parseInt message = 11 | numberLiteral NumberLiteralOptions.DefaultInteger message 12 | |>> fun n -> int n.String 13 | 14 | let private parseString message = 15 | between (pchar '\"') (pchar '\"') (manyChars (noneOf "\"")) message 16 | 17 | let private parseGetTimeout : Parser = 18 | skipString "get-timeout" .>> spaces 19 | |>> fun () -> GetTimeout 20 | 21 | let private parseSetTimeout : Parser = 22 | skipString "set-timeout" .>> spaces 23 | >>. parseInt "The 'set-timeout' command requires one integer argument." 24 | |>> SetTimeout 25 | 26 | let private parseEcho : Parser = 27 | skipString "echo" .>> spaces 28 | >>. parseString "The echo command requires one quoted string argument." 29 | |>> Echo 30 | 31 | let private choices = [| parseGetTimeout <|> parseSetTimeout <|> parseEcho |] 32 | 33 | let private choose reply = choice choices reply 34 | 35 | let parse : Parser = 36 | (spaces .>> skipChar '#' .>> spaces >>. choose) 37 | 38 | -------------------------------------------------------------------------------- /Machete.Runtime/HostObjects/Iterables/HStringIterator.cs: -------------------------------------------------------------------------------- 1 | using Machete.Core; 2 | 3 | namespace Machete.Runtime.HostObjects.Iterables 4 | { 5 | public sealed class HStringIterator : HIteratorBase 6 | { 7 | private readonly IString _value; 8 | private readonly int _length; 9 | private int _index; 10 | private bool _initialized; 11 | private bool _complete; 12 | 13 | public HStringIterator(IEnvironment environment, IString value) 14 | : base(environment) 15 | { 16 | _value = value; 17 | _length = value.BaseValue.Length; 18 | _index = -1; 19 | } 20 | 21 | public override IDynamic Current(IEnvironment environment, IArgs args) 22 | { 23 | if (!_initialized) 24 | throw environment.CreateTypeError(""); 25 | return environment.CreateString(_value.BaseValue.Substring(_index, 1)); 26 | } 27 | 28 | public override IDynamic Next(IEnvironment environment, IArgs args) 29 | { 30 | if (_complete) 31 | return environment.False; 32 | _initialized = true; 33 | if (++_index < _length) 34 | return environment.True; 35 | _complete = true; 36 | return environment.False; 37 | } 38 | } 39 | } -------------------------------------------------------------------------------- /Machete.Runtime/NativeObjects/BuiltinObjects/BConstructor.cs: -------------------------------------------------------------------------------- 1 | using Machete.Core; 2 | using Machete.Runtime.RuntimeTypes.LanguageTypes; 3 | 4 | namespace Machete.Runtime.NativeObjects.BuiltinObjects 5 | { 6 | public abstract class BConstructor : LObject, ICallable, IConstructable, IHasInstance 7 | { 8 | public BConstructor(IEnvironment environment) 9 | : base (environment) 10 | { 11 | 12 | } 13 | 14 | public override void Initialize() 15 | { 16 | Class = "Function"; 17 | Extensible = true; 18 | Prototype = Environment.FunctionPrototype; 19 | base.Initialize(); 20 | } 21 | 22 | IDynamic ICallable.Call(IEnvironment environment, IDynamic thisBinding, IArgs args) 23 | { 24 | using (var newContext = environment.EnterContext()) 25 | { 26 | Environment.Context.ThisBinding = thisBinding; 27 | return Call(environment, args); 28 | } 29 | } 30 | 31 | protected abstract IDynamic Call(IEnvironment environment, IArgs args); 32 | 33 | public abstract IObject Construct(IEnvironment environment, IArgs args); 34 | 35 | public bool HasInstance(IDynamic value) 36 | { 37 | return Environment.Instanceof(value, this); 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /Machete.Runtime/NativeObjects/BuiltinObjects/CBoolean.cs: -------------------------------------------------------------------------------- 1 | using Machete.Core; 2 | using Machete.Runtime.RuntimeTypes.LanguageTypes; 3 | 4 | namespace Machete.Runtime.NativeObjects.BuiltinObjects.ConstructorObjects 5 | { 6 | public sealed class CBoolean : BConstructor 7 | { 8 | public CBoolean(IEnvironment environment) 9 | : base(environment) 10 | { 11 | } 12 | 13 | public override void Initialize() 14 | { 15 | base.Initialize(); 16 | DefineOwnProperty("length", Environment.CreateDataDescriptor(Environment.CreateNumber(1.0), false, false, false), false); 17 | DefineOwnProperty("prototype", Environment.CreateDataDescriptor(Environment.BooleanPrototype, false, false, false), false); 18 | } 19 | 20 | protected override IDynamic Call(IEnvironment environment, IArgs args) 21 | { 22 | return args[0].ConvertToBoolean(); 23 | } 24 | 25 | public override IObject Construct(IEnvironment environment, IArgs args) 26 | { 27 | var obj = new NBoolean(environment); 28 | obj.Class = "Boolean"; 29 | obj.Extensible = true; 30 | obj.PrimitiveValue = args[0].ConvertToBoolean(); 31 | obj.Prototype = environment.BooleanPrototype; 32 | return obj; 33 | } 34 | } 35 | } -------------------------------------------------------------------------------- /Machete.Runtime/HostObjects/Iterables/HIteratorBase.cs: -------------------------------------------------------------------------------- 1 | using Machete.Core; 2 | using Machete.Core.Generators; 3 | using Machete.Runtime.NativeObjects.BuiltinObjects; 4 | using Machete.Runtime.RuntimeTypes.LanguageTypes; 5 | 6 | namespace Machete.Runtime.HostObjects 7 | { 8 | public abstract class HIteratorBase : LObject 9 | { 10 | public BFunction CurrentBuiltinFunction { get; private set; } 11 | public BFunction NextBuiltinFunction { get; private set; } 12 | 13 | public HIteratorBase(IEnvironment environment) 14 | : base(environment) 15 | { 16 | Class = "Iterator"; 17 | Extensible = true; 18 | Prototype = environment.ObjectPrototype; 19 | 20 | CurrentBuiltinFunction = new BFunction(environment, Current, ReadOnlyList.Empty); 21 | NextBuiltinFunction = new BFunction(environment, Next, ReadOnlyList.Empty); 22 | 23 | new LObject.Builder(this) 24 | .SetAttributes(false, false, false) 25 | .AppendAccessorProperty("current", CurrentBuiltinFunction, null) 26 | .AppendDataProperty("next", NextBuiltinFunction); 27 | } 28 | 29 | public abstract IDynamic Current(IEnvironment environment, IArgs args); 30 | 31 | public abstract IDynamic Next(IEnvironment environment, IArgs args); 32 | } 33 | } -------------------------------------------------------------------------------- /Machete.Core/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | using Machete.Core; 5 | 6 | [assembly: AssemblyTitle("Machete.Core")] 7 | [assembly: AssemblyDescription(AssemblyInfo.Description)] 8 | [assembly: AssemblyConfiguration(AssemblyInfo.Configuration)] 9 | [assembly: AssemblyCompany(AssemblyInfo.Company)] 10 | [assembly: AssemblyProduct(AssemblyInfo.Product)] 11 | [assembly: AssemblyCopyright(AssemblyInfo.Copyright)] 12 | [assembly: AssemblyTrademark(AssemblyInfo.Trademark)] 13 | [assembly: AssemblyCulture(AssemblyInfo.Culture)] 14 | [assembly: ComVisible(false)] 15 | [assembly: Guid("98a98e20-6bfb-4543-b576-3bb38a6cf9ad")] 16 | [assembly: AssemblyVersion(AssemblyInfo.Version)] 17 | [assembly: AssemblyFileVersion(AssemblyInfo.Version)] 18 | 19 | namespace Machete.Core 20 | { 21 | public static class AssemblyInfo 22 | { 23 | public const string Version = "0.5.11.0652"; 24 | public const string Description = "Machete - A scripting runtime for .NET"; 25 | public const string Configuration = ""; 26 | public const string Company = ""; 27 | public const string Product = "Machete"; 28 | public const string Copyright = "Copyright © 2019 Matthew O'Brien"; 29 | public const string Trademark = ""; 30 | public const string Culture = ""; 31 | } 32 | } -------------------------------------------------------------------------------- /Machete.Tests/Statements/BreakStatement.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Xunit; 3 | 4 | namespace Machete.Tests 5 | { 6 | public class BreakStatement : TestBase 7 | { 8 | [Fact(DisplayName = "12.8 The break Statement -> break [no LineTerminator here] Identifieropt ;")] 9 | public void Test128A() 10 | { 11 | var script = @" 12 | var i = 0; 13 | while (true) { 14 | i++; 15 | if (i === 10) 16 | break; 17 | } 18 | return i; 19 | "; 20 | Assert.Equal(10.0, (double)Engine.ExecuteScript(script)); 21 | } 22 | 23 | [Fact(DisplayName = "12.8 The break Statement -> break; with no loop or switch")] 24 | public void Test128B() 25 | { 26 | var script = @" 27 | break; 28 | "; 29 | var r = Engine.ExecuteScript(script); 30 | Assert.IsAssignableFrom(r); 31 | } 32 | 33 | [Fact(DisplayName = "12.8 The break Statement -> break Identifier; missing label")] 34 | public void Test128C() 35 | { 36 | var script = @" 37 | break Identifier; 38 | "; 39 | var r = Engine.ExecuteScript(script); 40 | Assert.IsAssignableFrom(r); 41 | } 42 | } 43 | } -------------------------------------------------------------------------------- /Machete.Runtime/NativeObjects/NString.cs: -------------------------------------------------------------------------------- 1 | using Machete.Core; 2 | using Machete.Runtime.RuntimeTypes.LanguageTypes; 3 | 4 | namespace Machete.Runtime.NativeObjects 5 | { 6 | public sealed class NString : LObject, IPrimitiveWrapper 7 | { 8 | public IDynamic PrimitiveValue { get; set; } 9 | 10 | public NString(IEnvironment environment) 11 | : base(environment) 12 | { 13 | 14 | } 15 | 16 | public override IPropertyDescriptor GetOwnProperty(string p) 17 | { 18 | // 15.5.5.2 [[GetOwnProperty]] ( P ) 19 | 20 | var desc = base.GetOwnProperty(p); 21 | if (desc != null) 22 | { 23 | return desc; 24 | } 25 | var pString = Environment.CreateString(p); 26 | var index = pString.ConvertToUInt32(); 27 | if (index.ConvertToString().BaseValue == p && index.BaseValue != 4294967295) 28 | { 29 | var str = ((IString)PrimitiveValue).BaseValue; 30 | var intIndex = (int)index.BaseValue; 31 | if (str.Length > intIndex) 32 | { 33 | var resultStr = Environment.CreateString(str.Substring(intIndex, 1)); 34 | return Environment.CreateDataDescriptor(resultStr, false, true, false); 35 | } 36 | } 37 | return null; 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /Machete.Interactive/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /Machete.Runtime/HostObjects/Iterables/HGeneratorIterable.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using Machete.Runtime.RuntimeTypes.LanguageTypes; 6 | using Machete.Core; 7 | using Machete.Runtime.NativeObjects.BuiltinObjects; 8 | using Machete.Core.Generators; 9 | 10 | namespace Machete.Runtime.HostObjects.Iterables 11 | { 12 | public sealed class HGeneratorIterable : HIterableBase 13 | { 14 | public ReadOnlyList Steps { get; private set; } 15 | public ReadOnlyList VariableDeclarations { get; private set; } 16 | public ILexicalEnvironment Scope { get; private set; } 17 | 18 | public HGeneratorIterable(IEnvironment environment, ReadOnlyList steps, ReadOnlyList variableDeclarations, ILexicalEnvironment scope) 19 | : base(environment) 20 | { 21 | Steps = steps; 22 | VariableDeclarations = variableDeclarations; 23 | Scope = scope; 24 | } 25 | 26 | public override IDynamic CreateIterator(IEnvironment environment, IArgs args) 27 | { 28 | var scope = Scope.NewDeclarativeEnvironment(); 29 | var generator = new Generator(new GeneratorSteps(Steps)); 30 | var iterator = new HGeneratorIterator(environment, generator, VariableDeclarations, scope); 31 | return iterator; 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /Machete.Tests/Statements/ContinueStatement.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Xunit; 3 | 4 | namespace Machete.Tests 5 | { 6 | public class ContinueStatement : TestBase 7 | { 8 | [Fact(DisplayName = "12.7 The continue Statement")] 9 | public void Test127A() 10 | { 11 | var script = @" 12 | var i = 0, run = true; 13 | while (run) { 14 | i++; 15 | if (i === 1) 16 | continue; 17 | 18 | run = false; 19 | } 20 | return i; 21 | "; 22 | Assert.Equal(2.0, (double)Engine.ExecuteScript(script)); 23 | } 24 | 25 | [Fact(DisplayName = "12.7 The continue Statement -> continue; with no loop or switch")] 26 | public void Test127B() 27 | { 28 | var script = @" 29 | continue; 30 | "; 31 | var r = Engine.ExecuteScript(script); 32 | Assert.IsAssignableFrom(r); 33 | } 34 | 35 | [Fact(DisplayName = "12.7 The continue Statement -> continue Identifier; missing label")] 36 | public void Test127C() 37 | { 38 | var script = @" 39 | continue Identifier; 40 | "; 41 | var r = Engine.ExecuteScript(script); 42 | Assert.IsAssignableFrom(r); 43 | } 44 | } 45 | } -------------------------------------------------------------------------------- /Machete.Tests/Expressions/RelationalOperators.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Xunit; 3 | 4 | namespace Machete.Tests 5 | { 6 | public class RelationalOperators : TestBase 7 | { 8 | [Fact(DisplayName = "11.8.1 The Less-than Operator ( < )")] 9 | public void Test1181() 10 | { 11 | Assert.True((bool)Engine.ExecuteScript("1 < 2")); 12 | } 13 | 14 | [Fact(DisplayName = "11.8.2 The Greater-than Operator ( > )")] 15 | public void Test1182() 16 | { 17 | Assert.True((bool)Engine.ExecuteScript("2 > 1")); 18 | } 19 | 20 | [Fact(DisplayName = "11.8.3 The Less-than-or-equal Operator ( <= )")] 21 | public void Test1183() 22 | { 23 | Assert.True((bool)Engine.ExecuteScript("2 <= 2")); 24 | } 25 | 26 | [Fact(DisplayName = "11.8.4 The Greater-than-or-equal Operator ( >= )")] 27 | public void Test1184() 28 | { 29 | Assert.True((bool)Engine.ExecuteScript("2 >= 2")); 30 | } 31 | 32 | [Fact(DisplayName = "11.8.6 The instanceof operator")] 33 | public void Test1186() 34 | { 35 | Assert.True((bool)Engine.ExecuteScript("new Object() instanceof Object")); 36 | } 37 | 38 | [Fact(DisplayName = "11.8.7 The in operator")] 39 | public void Test1187() 40 | { 41 | Assert.True((bool)Engine.ExecuteScript("'create' in Object")); 42 | } 43 | } 44 | } -------------------------------------------------------------------------------- /Machete.Runtime/NativeObjects/NBoundFunction.cs: -------------------------------------------------------------------------------- 1 | using Machete.Core; 2 | 3 | namespace Machete.Runtime.NativeObjects 4 | { 5 | public class NBoundFunction : NFunction 6 | { 7 | public IObject TargetFunction { get; set; } 8 | public IDynamic BoundThis { get; set; } 9 | public IArgs BoundArguments { get; set; } 10 | 11 | public NBoundFunction(IEnvironment enviroment) 12 | : base(enviroment) 13 | { 14 | 15 | } 16 | 17 | public override IDynamic Call(IEnvironment environment, IDynamic thisBinding, IArgs args) 18 | { 19 | var func = TargetFunction as NFunction; 20 | return func.Call(environment, BoundThis, environment.ConcatArgs(BoundArguments, args)); 21 | } 22 | 23 | public override IObject Construct(IEnvironment environment, IArgs args) 24 | { 25 | var func = TargetFunction as NFunction; 26 | if (func == null) 27 | { 28 | throw Environment.CreateTypeError(""); 29 | } 30 | return func.Construct(environment, environment.ConcatArgs(BoundArguments, args)); 31 | } 32 | 33 | public override bool HasInstance(IDynamic value) 34 | { 35 | var func = TargetFunction as IHasInstance; 36 | if (func == null) 37 | { 38 | throw Environment.CreateTypeError(""); 39 | } 40 | return func.HasInstance(value); 41 | } 42 | } 43 | } -------------------------------------------------------------------------------- /Machete.Tests/Lexical Conventions/LineTerminators.cs: -------------------------------------------------------------------------------- 1 | using Machete.Core; 2 | using Xunit; 3 | 4 | namespace Machete.Tests.Lexical_Conventions 5 | { 6 | public sealed class LineTerminators : TestBase 7 | { 8 | //[Fact(DisplayName = "07.03 Line Terminators: LF")] 9 | //public void Test0703A() 10 | //{ 11 | // var r = Engine.ExecuteScriptToDynamic("\u000A2"); 12 | // Assert.IsAssignableFrom(r); 13 | // Assert.Equal(2.0, ((INumber)r).BaseValue); 14 | //} 15 | 16 | //[Fact(DisplayName = "07.03 Line Terminators: CR")] 17 | //public void Test0703B() 18 | //{ 19 | // var r = Engine.ExecuteScriptToDynamic("\u000D2"); 20 | // Assert.IsAssignableFrom(r); 21 | // Assert.Equal(2.0, ((INumber)r).BaseValue); 22 | //} 23 | 24 | //[Fact(DisplayName = "07.03 Line Terminators: LS")] 25 | //public void Test0703C() 26 | //{ 27 | // var r = Engine.ExecuteScriptToDynamic("\u20282"); 28 | // Assert.IsAssignableFrom(r); 29 | // Assert.Equal(2.0, ((INumber)r).BaseValue); 30 | //} 31 | 32 | //[Fact(DisplayName = "07.03 Line Terminators: PS")] 33 | //public void Test0703D() 34 | //{ 35 | // var r = Engine.ExecuteScriptToDynamic("\u20292"); 36 | // Assert.IsAssignableFrom(r); 37 | // Assert.Equal(2.0, ((INumber)r).BaseValue); 38 | //} 39 | } 40 | } -------------------------------------------------------------------------------- /Machete.Runtime/HostObjects/Iterables/HMapIterator.cs: -------------------------------------------------------------------------------- 1 | using Machete.Core; 2 | 3 | namespace Machete.Runtime.HostObjects.Iterables 4 | { 5 | public sealed class HMapIterator : HIteratorBase 6 | { 7 | private readonly Iterator _iterator; 8 | private readonly ICallable _mapping; 9 | private IDynamic _current; 10 | private bool _initialized; 11 | private bool _complete; 12 | 13 | public HMapIterator(IEnvironment environment, Iterator iterator, ICallable mapping) 14 | : base(environment) 15 | { 16 | _iterator = iterator; 17 | _mapping = mapping; 18 | } 19 | 20 | public override IDynamic Current(IEnvironment environment, IArgs args) 21 | { 22 | if (!_initialized) 23 | throw environment.CreateTypeError(""); 24 | return _current; 25 | } 26 | 27 | public override IDynamic Next(IEnvironment environment, IArgs args) 28 | { 29 | if (_complete) 30 | return environment.False; 31 | _initialized = true; 32 | while (_iterator.Next()) 33 | { 34 | var callArgs = environment.CreateArgs(new[] { _iterator.Current }); 35 | _current = _mapping.Call(environment, environment.Undefined, callArgs); 36 | return environment.True; 37 | } 38 | _complete = true; 39 | return environment.False; 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /Machete.Runtime/NativeObjects/BuiltinObjects/BJson.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using Machete.Runtime.RuntimeTypes.LanguageTypes; 6 | using Machete.Core; 7 | 8 | namespace Machete.Runtime.NativeObjects.BuiltinObjects 9 | { 10 | public sealed class BJson : LObject 11 | { 12 | public BJson(IEnvironment environment) 13 | : base(environment) 14 | { 15 | 16 | } 17 | 18 | public override void Initialize() 19 | { 20 | Class = "JSON"; 21 | Extensible = true; 22 | Prototype = Environment.ObjectPrototype; 23 | base.Initialize(); 24 | } 25 | 26 | [BuiltinFunction("parse", "text", "reviver"), DataDescriptor(true, false, true)] 27 | internal static IDynamic Parse(IEnvironment environment, IArgs args) 28 | { 29 | var text = args[0]; 30 | var reviver = args[1]; 31 | return Machete.Compiler.JsonParser.Parse(environment, text, reviver); 32 | } 33 | 34 | [BuiltinFunction("stringify", "value", "replacer", "space"), DataDescriptor(true, false, true)] 35 | internal static IDynamic Stringify(IEnvironment environment, IArgs args) 36 | { 37 | var value = args[0]; 38 | var replacer = args[1]; 39 | var space = args[2]; 40 | return Machete.Compiler.JsonParser.Stringify(environment, value, replacer, space); 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /Machete.Runtime/NativeObjects/BuiltinObjects/CError.cs: -------------------------------------------------------------------------------- 1 | using Machete.Core; 2 | using Machete.Runtime.RuntimeTypes.LanguageTypes; 3 | 4 | namespace Machete.Runtime.NativeObjects.BuiltinObjects.ConstructorObjects 5 | { 6 | public sealed class CError : BConstructor 7 | { 8 | public CError(IEnvironment environment) 9 | : base(environment) 10 | { 11 | 12 | } 13 | 14 | public override void Initialize() 15 | { 16 | base.Initialize(); 17 | DefineOwnProperty("length", Environment.CreateDataDescriptor(Environment.CreateNumber(1.0), false, false, false), false); 18 | DefineOwnProperty("prototype", Environment.CreateDataDescriptor(Environment.ErrorPrototype, false, false, false), false); 19 | } 20 | 21 | protected override IDynamic Call(IEnvironment environment, IArgs args) 22 | { 23 | return Construct(environment, args); 24 | } 25 | 26 | public override IObject Construct(IEnvironment environment, IArgs args) 27 | { 28 | var message = args[0].ConvertToString(); 29 | if (message.BaseValue == "undefined") 30 | { 31 | message = environment.CreateString(""); 32 | } 33 | var error = new NError(environment); 34 | error.Class = "Error"; 35 | error.Extensible = true; 36 | error.Prototype = environment.ErrorPrototype; 37 | error.Put("message", message, false); 38 | return error; 39 | } 40 | } 41 | } -------------------------------------------------------------------------------- /Machete.Core/Iterator.cs: -------------------------------------------------------------------------------- 1 | namespace Machete.Core 2 | { 3 | public sealed class Iterator 4 | { 5 | private readonly IEnvironment _environment; 6 | private readonly IObject _iterator; 7 | private readonly ICallable _next; 8 | 9 | public Iterator(IEnvironment environment, IDynamic iterable) 10 | { 11 | _environment = environment; 12 | 13 | var o = iterable.ConvertToObject(); 14 | var createIterator = o.Get("createIterator") as ICallable; 15 | if (createIterator == null) 16 | throw environment.CreateTypeError("The object supplied does not contain a callable property named 'createIterator'."); 17 | _iterator = createIterator.Call(environment, iterable, environment.EmptyArgs).ConvertToObject(); 18 | if (!_iterator.HasProperty("current")) 19 | throw environment.CreateTypeError("The object returned from the iterable supplied does not have a property named 'current'."); 20 | _next = _iterator.Get("next") as ICallable; 21 | if (_next == null) 22 | throw environment.CreateTypeError("The object returned from the iterable supplied does not have a callable property named 'next'."); 23 | } 24 | 25 | public IDynamic Current 26 | { 27 | get { return _iterator.Get("current"); } 28 | } 29 | 30 | public bool Next() 31 | { 32 | return _next.Call(_environment, _environment.Undefined, _environment.EmptyArgs).ConvertToBoolean().BaseValue; 33 | } 34 | } 35 | } -------------------------------------------------------------------------------- /Machete.Runtime/NativeObjects/BuiltinObjects/CEvalError.cs: -------------------------------------------------------------------------------- 1 | using Machete.Core; 2 | using Machete.Runtime.RuntimeTypes.LanguageTypes; 3 | 4 | namespace Machete.Runtime.NativeObjects.BuiltinObjects.ConstructorObjects 5 | { 6 | public sealed class CEvalError : BConstructor 7 | { 8 | public CEvalError(IEnvironment environment) 9 | : base(environment) 10 | { 11 | 12 | } 13 | 14 | public sealed override void Initialize() 15 | { 16 | base.Initialize(); 17 | DefineOwnProperty("length", Environment.CreateDataDescriptor(Environment.CreateNumber(1.0), false, false, false), false); 18 | DefineOwnProperty("prototype", Environment.CreateDataDescriptor(Environment.EvalErrorPrototype, false, false, false), false); 19 | } 20 | 21 | protected sealed override IDynamic Call(IEnvironment environment, IArgs args) 22 | { 23 | return Construct(environment, args); 24 | } 25 | 26 | public sealed override IObject Construct(IEnvironment environment, IArgs args) 27 | { 28 | var message = args[0].ConvertToString(); 29 | if (message.BaseValue == "undefined") 30 | { 31 | message = environment.CreateString(""); 32 | } 33 | var error = new NEvalError(environment); 34 | error.Class = "Error"; 35 | error.Extensible = true; 36 | error.Prototype = environment.EvalErrorPrototype; 37 | error.Put("message", message, false); 38 | return error; 39 | } 40 | } 41 | } -------------------------------------------------------------------------------- /Machete.Runtime/NativeObjects/BuiltinObjects/CUriError.cs: -------------------------------------------------------------------------------- 1 | using Machete.Core; 2 | using Machete.Runtime.RuntimeTypes.LanguageTypes; 3 | 4 | namespace Machete.Runtime.NativeObjects.BuiltinObjects.ConstructorObjects 5 | { 6 | public sealed class CUriError : BConstructor 7 | { 8 | public CUriError(IEnvironment environment) 9 | : base(environment) 10 | { 11 | 12 | } 13 | 14 | public sealed override void Initialize() 15 | { 16 | base.Initialize(); 17 | DefineOwnProperty("length", Environment.CreateDataDescriptor(Environment.CreateNumber(1.0), false, false, false), false); 18 | DefineOwnProperty("prototype", Environment.CreateDataDescriptor(Environment.UriErrorPrototype, false, false, false), false); 19 | } 20 | 21 | protected sealed override IDynamic Call(IEnvironment environment, IArgs args) 22 | { 23 | return ((IConstructable)this).Construct(environment, args); 24 | } 25 | 26 | public sealed override IObject Construct(IEnvironment environment, IArgs args) 27 | { 28 | var message = args[0].ConvertToString(); 29 | if (message.BaseValue == "undefined") 30 | { 31 | message = environment.CreateString(""); 32 | } 33 | var error = new NUriError(environment); 34 | error.Class = "Error"; 35 | error.Extensible = true; 36 | error.Prototype = environment.UriErrorPrototype; 37 | error.Put("message", message, false); 38 | return error; 39 | } 40 | } 41 | } -------------------------------------------------------------------------------- /Machete.Runtime/HostObjects/Iterables/HFilterIterator.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using Machete.Core; 6 | 7 | namespace Machete.Runtime.HostObjects.Iterables 8 | { 9 | public sealed class HFilterIterator : HIteratorBase 10 | { 11 | private readonly Iterator _iterator; 12 | private readonly ICallable _predicate; 13 | private bool _initialized; 14 | private bool _complete; 15 | 16 | public HFilterIterator(IEnvironment environment, Iterator iterator, ICallable predicate) 17 | : base(environment) 18 | { 19 | _iterator = iterator; 20 | _predicate = predicate; 21 | } 22 | 23 | public override IDynamic Current(IEnvironment environment, IArgs args) 24 | { 25 | if (!_initialized) 26 | throw environment.CreateTypeError(""); 27 | return _iterator.Current; 28 | } 29 | 30 | public override IDynamic Next(IEnvironment environment, IArgs args) 31 | { 32 | if (_complete) 33 | return environment.False; 34 | _initialized = true; 35 | while (_iterator.Next()) 36 | { 37 | var callArgs = environment.CreateArgs(new[] { _iterator.Current }); 38 | if (_predicate.Call(environment, environment.Undefined, callArgs).ConvertToBoolean().BaseValue) 39 | return environment.True; 40 | } 41 | _complete = true; 42 | return environment.False; 43 | } 44 | } 45 | } -------------------------------------------------------------------------------- /Machete.Runtime/NativeObjects/BuiltinObjects/CTypeError.cs: -------------------------------------------------------------------------------- 1 | using Machete.Core; 2 | using Machete.Runtime.RuntimeTypes.LanguageTypes; 3 | 4 | namespace Machete.Runtime.NativeObjects.BuiltinObjects.ConstructorObjects 5 | { 6 | public sealed class CTypeError : BConstructor 7 | { 8 | public CTypeError(IEnvironment environment) 9 | : base(environment) 10 | { 11 | 12 | } 13 | 14 | public sealed override void Initialize() 15 | { 16 | base.Initialize(); 17 | DefineOwnProperty("length", Environment.CreateDataDescriptor(Environment.CreateNumber(1.0), false, false, false), false); 18 | DefineOwnProperty("prototype", Environment.CreateDataDescriptor(Environment.TypeErrorPrototype, false, false, false), false); 19 | } 20 | 21 | protected sealed override IDynamic Call(IEnvironment environment, IArgs args) 22 | { 23 | return ((IConstructable)this).Construct(environment, args); 24 | } 25 | 26 | public sealed override IObject Construct(IEnvironment environment, IArgs args) 27 | { 28 | var message = args[0].ConvertToString(); 29 | if (message.BaseValue == "undefined") 30 | { 31 | message = environment.CreateString(""); 32 | } 33 | var error = new NTypeError(environment); 34 | error.Class = "Error"; 35 | error.Extensible = true; 36 | error.Prototype = environment.TypeErrorPrototype; 37 | error.Put("message", message, false); 38 | return error; 39 | } 40 | } 41 | } -------------------------------------------------------------------------------- /Machete.Runtime/NativeObjects/BuiltinObjects/CRangeError.cs: -------------------------------------------------------------------------------- 1 | using Machete.Core; 2 | using Machete.Runtime.RuntimeTypes.LanguageTypes; 3 | 4 | namespace Machete.Runtime.NativeObjects.BuiltinObjects.ConstructorObjects 5 | { 6 | public sealed class CRangeError : BConstructor 7 | { 8 | public CRangeError(IEnvironment environment) 9 | : base(environment) 10 | { 11 | 12 | } 13 | 14 | public sealed override void Initialize() 15 | { 16 | base.Initialize(); 17 | DefineOwnProperty("length", Environment.CreateDataDescriptor(Environment.CreateNumber(1.0), false, false, false), false); 18 | DefineOwnProperty("prototype", Environment.CreateDataDescriptor(Environment.RangeErrorPrototype, false, false, false), false); 19 | } 20 | 21 | protected sealed override IDynamic Call(IEnvironment environment, IArgs args) 22 | { 23 | return ((IConstructable)this).Construct(environment, args); 24 | } 25 | 26 | public sealed override IObject Construct(IEnvironment environment, IArgs args) 27 | { 28 | var message = args[0].ConvertToString(); 29 | if (message.BaseValue == "undefined") 30 | { 31 | message = environment.CreateString(""); 32 | } 33 | var error = new NRangeError(environment); 34 | error.Class = "Error"; 35 | error.Extensible = true; 36 | error.Prototype = environment.RangeErrorPrototype; 37 | error.Put("message", message, false); 38 | return error; 39 | } 40 | } 41 | } -------------------------------------------------------------------------------- /Machete.Runtime/NativeObjects/BuiltinObjects/CSyntaxError.cs: -------------------------------------------------------------------------------- 1 | using Machete.Core; 2 | using Machete.Runtime.RuntimeTypes.LanguageTypes; 3 | 4 | namespace Machete.Runtime.NativeObjects.BuiltinObjects.ConstructorObjects 5 | { 6 | public sealed class CSyntaxError : BConstructor 7 | { 8 | public CSyntaxError(IEnvironment environment) 9 | : base(environment) 10 | { 11 | 12 | } 13 | 14 | public sealed override void Initialize() 15 | { 16 | base.Initialize(); 17 | DefineOwnProperty("length", Environment.CreateDataDescriptor(Environment.CreateNumber(1.0), false, false, false), false); 18 | DefineOwnProperty("prototype", Environment.CreateDataDescriptor(Environment.SyntaxErrorPrototype, false, false, false), false); 19 | } 20 | 21 | protected sealed override IDynamic Call(IEnvironment environment, IArgs args) 22 | { 23 | return ((IConstructable)this).Construct(environment, args); 24 | } 25 | 26 | public sealed override IObject Construct(IEnvironment environment, IArgs args) 27 | { 28 | var message = args[0].ConvertToString(); 29 | if (message.BaseValue == "undefined") 30 | { 31 | message = environment.CreateString(""); 32 | } 33 | var error = new NSyntaxError(environment); 34 | error.Class = "Error"; 35 | error.Extensible = true; 36 | error.Prototype = environment.SyntaxErrorPrototype; 37 | error.Put("message", message, false); 38 | return error; 39 | } 40 | } 41 | } -------------------------------------------------------------------------------- /Machete.Tests/Specification/Tests_07_Lexical_Conventions/Tests_07_03_LineTerminators.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Machete.Parser; 3 | using Microsoft.FSharp.Core; 4 | using Xunit; 5 | 6 | namespace Machete.Tests.Specification.Tests_07_Lexical_Conventions 7 | { 8 | public class Tests_07_03_LineTerminators : TestBase 9 | { 10 | [Fact(DisplayName = "07.03 Line Terminators: LF")] 11 | public void Test0703A() 12 | { 13 | var r = RunParser(InputElementParsers.parseLineTerminator, "\u000A"); 14 | Assert.True(r.IsLineTerminator, "The LF character was not parsed as a Line Terminator."); 15 | } 16 | 17 | [Fact(DisplayName = "07.03 Line Terminators: CR")] 18 | public void Test0703B() 19 | { 20 | var r = RunParser(InputElementParsers.parseLineTerminator, "\u000D"); 21 | Assert.True(r.IsLineTerminator, "The CR character was not parsed as a Line Terminator."); 22 | } 23 | 24 | [Fact(DisplayName = "07.03 Line Terminators: LS")] 25 | public void Test0703C() 26 | { 27 | var r = RunParser(InputElementParsers.parseLineTerminator, "\u2028"); 28 | Assert.True(r.IsLineTerminator, "The LS character was not parsed as a Line Terminator."); 29 | } 30 | 31 | [Fact(DisplayName = "07.03 Line Terminators: PS")] 32 | public void Test0703D() 33 | { 34 | var r = RunParser(InputElementParsers.parseLineTerminator, "\u2029"); 35 | Assert.True(r.IsLineTerminator, "The PS character was not parsed as a Line Terminator."); 36 | } 37 | } 38 | } -------------------------------------------------------------------------------- /Machete.Runtime/HostObjects/Iterables/HArrayIterator.cs: -------------------------------------------------------------------------------- 1 | using Machete.Core; 2 | 3 | namespace Machete.Runtime.HostObjects.Iterables 4 | { 5 | public sealed class HArrayIterator : HIteratorBase 6 | { 7 | private readonly IObject _array; 8 | private readonly uint _length; 9 | private uint _index; 10 | private bool _initialized; 11 | private bool _complete; 12 | 13 | public HArrayIterator(IEnvironment environment, IObject array) 14 | : base(environment) 15 | { 16 | _array = array; 17 | _length = (uint)array.Get("length").ConvertToUInt32().BaseValue; 18 | } 19 | 20 | public override IDynamic Current(IEnvironment environment, IArgs args) 21 | { 22 | if (!_initialized) 23 | throw environment.CreateTypeError(""); 24 | return _array.Get(_index.ToString()); 25 | } 26 | 27 | public override IDynamic Next(IEnvironment environment, IArgs args) 28 | { 29 | if (_complete) 30 | return environment.False; 31 | if (!_initialized) 32 | { 33 | _initialized = true; 34 | } 35 | else 36 | { 37 | _index++; 38 | } 39 | do 40 | { 41 | if (_array.HasProperty(_index.ToString())) 42 | { 43 | return environment.True; 44 | } 45 | } 46 | while (++_index < _length); 47 | _complete = true; 48 | return environment.False; 49 | } 50 | } 51 | } -------------------------------------------------------------------------------- /Machete.Runtime/NativeObjects/BuiltinObjects/CReferenceError.cs: -------------------------------------------------------------------------------- 1 | using Machete.Core; 2 | using Machete.Runtime.RuntimeTypes.LanguageTypes; 3 | 4 | namespace Machete.Runtime.NativeObjects.BuiltinObjects.ConstructorObjects 5 | { 6 | public sealed class CReferenceError : BConstructor 7 | { 8 | public CReferenceError(IEnvironment environment) 9 | : base(environment) 10 | { 11 | 12 | } 13 | 14 | public sealed override void Initialize() 15 | { 16 | base.Initialize(); 17 | DefineOwnProperty("length", Environment.CreateDataDescriptor(Environment.CreateNumber(1.0), false, false, false), false); 18 | DefineOwnProperty("prototype", Environment.CreateDataDescriptor(Environment.ReferenceErrorPrototype, false, false, false), false); 19 | } 20 | 21 | protected sealed override IDynamic Call(IEnvironment environment, IArgs args) 22 | { 23 | return ((IConstructable)this).Construct(environment, args); 24 | } 25 | 26 | public sealed override IObject Construct(IEnvironment environment, IArgs args) 27 | { 28 | var message = args[0].ConvertToString(); 29 | if (message.BaseValue == "undefined") 30 | { 31 | message = environment.CreateString(""); 32 | } 33 | var error = new NReferenceError(environment); 34 | error.Class = "Error"; 35 | error.Extensible = true; 36 | error.Prototype = environment.ReferenceErrorPrototype; 37 | error.Put("message", message, false); 38 | return error; 39 | } 40 | } 41 | } -------------------------------------------------------------------------------- /Machete.Runtime/HostObjects/HLazy.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using Machete.Runtime.RuntimeTypes.LanguageTypes; 6 | using Machete.Core; 7 | 8 | namespace Machete.Runtime.HostObjects 9 | { 10 | public sealed class HLazy : LObject 11 | { 12 | private readonly Lazy _underlying; 13 | 14 | public HLazy(IEnvironment environment, Func createValue) 15 | : base(environment) 16 | { 17 | _underlying = new Lazy(createValue); 18 | } 19 | 20 | public override IPropertyDescriptor GetOwnProperty(string p) 21 | { 22 | return _underlying.Value.GetOwnProperty(p); 23 | } 24 | 25 | public override IPropertyDescriptor GetProperty(string p) 26 | { 27 | return _underlying.Value.GetProperty(p); 28 | } 29 | 30 | public override IDynamic Get(string p) 31 | { 32 | return _underlying.Value.Get(p); 33 | } 34 | 35 | public override bool CanPut(string p) 36 | { 37 | return _underlying.Value.CanPut(p); 38 | } 39 | 40 | public override bool HasProperty(string p) 41 | { 42 | return _underlying.Value.HasProperty(p); 43 | } 44 | 45 | public override IDynamic DefaultValue(string hint) 46 | { 47 | return _underlying.Value.DefaultValue(hint); 48 | } 49 | 50 | public override bool DefineOwnProperty(string p, IPropertyDescriptor desc, bool @throw) 51 | { 52 | return _underlying.Value.DefineOwnProperty(p, desc, @throw); 53 | } 54 | } 55 | } -------------------------------------------------------------------------------- /Machete.Runtime/NativeObjects/BuiltinObjects/PError.cs: -------------------------------------------------------------------------------- 1 | using Machete.Core; 2 | using Machete.Runtime.RuntimeTypes.LanguageTypes; 3 | 4 | namespace Machete.Runtime.NativeObjects.BuiltinObjects.PrototypeObjects 5 | { 6 | public sealed class PError : LObject 7 | { 8 | public PError(IEnvironment environment) 9 | : base(environment) 10 | { 11 | 12 | } 13 | 14 | public override void Initialize() 15 | { 16 | Class = "Error"; 17 | Extensible = true; 18 | DefineOwnProperty("name", Environment.CreateDataDescriptor(Environment.CreateString("Error"), true, false, true), false); 19 | DefineOwnProperty("message", Environment.CreateDataDescriptor(Environment.CreateString(""), true, false, true), false); 20 | base.Initialize(); 21 | } 22 | 23 | 24 | [BuiltinFunction("toString"), DataDescriptor(true, false, true)] 25 | internal static IDynamic ToString(IEnvironment environment, IArgs args) 26 | { 27 | var obj = environment.Context.ThisBinding.ConvertToObject(); 28 | var name = obj.Get("name").ConvertToString().BaseValue; 29 | var message = obj.Get("message").ConvertToString().BaseValue; 30 | 31 | if (name == "undefined") 32 | { 33 | if (message == "undefined") 34 | { 35 | return environment.CreateString("Error"); 36 | } 37 | return environment.CreateString("Error: " + message); 38 | } 39 | else 40 | { 41 | if (message == "undefined") 42 | { 43 | return environment.CreateString(name); 44 | } 45 | return environment.CreateString(name + ": " + message); 46 | } 47 | } 48 | } 49 | } -------------------------------------------------------------------------------- /Machete.Tests/Expressions/LeftHandSideExpressions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Xunit; 3 | 4 | namespace Machete.Tests 5 | { 6 | public class LeftHandSideExpressions : TestBase 7 | { 8 | [Fact(DisplayName = "11.2.1 Property Accessors -> Dot Notation")] 9 | public void Test1121A() 10 | { 11 | Assert.Equal(1.0, (double)Engine.ExecuteScript("this.Object.length")); 12 | } 13 | 14 | [Fact(DisplayName = "11.2.1 Property Accessors -> Bracket Notation")] 15 | public void Test1121B() 16 | { 17 | Assert.Equal(1.0, (double)Engine.ExecuteScript("this['Object']['length']")); 18 | } 19 | 20 | [Fact(DisplayName = "11.2.1 Property Accessors -> Mixed Notation")] 21 | public void Test1121C() 22 | { 23 | Assert.Equal(1.0, (double)Engine.ExecuteScript("this['Object'].length")); 24 | } 25 | 26 | [Fact(DisplayName = "11.2.2 The new Operator")] 27 | public void Test1122() 28 | { 29 | Assert.Equal("object", (string)Engine.ExecuteScript("typeof new Object()")); 30 | } 31 | 32 | [Fact(DisplayName = "11.2.3 Function Calls")] 33 | public void Test1123() 34 | { 35 | Assert.Equal(100.0, (double)Engine.ExecuteScript("parseInt('100', 10);")); 36 | } 37 | 38 | [Fact(DisplayName = "11.2.4 Argument Lists")] 39 | public void Test1124() 40 | { 41 | Assert.Equal("1,2,3,4,5", (string)Engine.ExecuteScript("new Array(1, 2, 3, 4, 5)")); 42 | Assert.Equal("1,2,3,4,5", (string)Engine.ExecuteScript("new Array ( 1, 2, 3, 4, 5 ) ")); 43 | } 44 | 45 | [Fact(DisplayName = "11.2.5 Function Expressions")] 46 | public void Test1125() 47 | { 48 | Assert.Equal("Param = 1", (string)Engine.ExecuteScript("(function(a) { return 'Param = ' + a; })(1);")); 49 | } 50 | } 51 | } -------------------------------------------------------------------------------- /Machete.Tests/Expressions/EqualityOperators.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Xunit; 3 | 4 | namespace Machete.Tests 5 | { 6 | public class EqualityOperators : TestBase 7 | { 8 | [Fact(DisplayName = "11.9.1 The Equals Operator ( == ): Same Type")] 9 | public void Test1191A() 10 | { 11 | ExpectTrue("1 == 1"); 12 | ExpectTrue("'' == ''"); 13 | } 14 | 15 | [Fact(DisplayName = "11.9.1 The Equals Operator ( == ): null == undefined")] 16 | public void Test1191B() 17 | { 18 | ExpectTrue("null == undefined"); 19 | } 20 | 21 | [Fact(DisplayName = "11.9.1 The Equals Operator ( == ): undefined == null")] 22 | public void Test1191C() 23 | { 24 | ExpectTrue("undefined == null"); 25 | } 26 | 27 | [Fact(DisplayName = "11.9.1 The Equals Operator ( == ): Number == String")] 28 | public void Test1191D() 29 | { 30 | ExpectTrue("2 == '2'"); 31 | ExpectFalse("3 == '2'"); 32 | } 33 | 34 | [Fact(DisplayName = "11.9.1 The Equals Operator ( == ): String == Number")] 35 | public void Test1191E() 36 | { 37 | ExpectTrue("'2' == 2"); 38 | ExpectFalse("'3' == 2"); 39 | } 40 | 41 | [Fact(DisplayName = "11.9.2 The Does-not-equals Operator ( != )")] 42 | public void Test1192() 43 | { 44 | Assert.True((bool)Engine.ExecuteScript("2 != '1'")); 45 | } 46 | 47 | [Fact(DisplayName = "11.9.4 The Strict Equals Operator ( === )")] 48 | public void Test1194() 49 | { 50 | Assert.True((bool)Engine.ExecuteScript("1 === 1")); 51 | } 52 | 53 | [Fact(DisplayName = "11.9.5 The Strict Does-not-equal Operator ( !== )")] 54 | public void Test1195() 55 | { 56 | Assert.True((bool)Engine.ExecuteScript("2 !== 1")); 57 | } 58 | } 59 | } -------------------------------------------------------------------------------- /Machete.Tests/Statements/TryStatement.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Xunit; 3 | 4 | namespace Machete.Tests 5 | { 6 | public class TryStatement : TestBase 7 | { 8 | [Fact(DisplayName = "12.14 The try Statement -> Try-Catch")] 9 | public void Test1214A() 10 | { 11 | const string script = @" 12 | var s = ''; 13 | try { 14 | s = 'A'; 15 | throw 'B'; 16 | } catch (e) { 17 | s = e; 18 | } 19 | return s; 20 | "; 21 | Assert.Equal("B", (string)Engine.ExecuteScript(script)); 22 | Assert.True((bool)Engine.ExecuteScript("delete s")); 23 | } 24 | 25 | [Fact(DisplayName = "12.14 The try Statement -> Try-Finally")] 26 | public void Test1214B() 27 | { 28 | const string script = @" 29 | var s = 'A'; 30 | try { 31 | throw 'Fail!'; 32 | } finally { 33 | s = 'B'; 34 | } 35 | "; 36 | Assert.IsAssignableFrom(Engine.ExecuteScript(script)); 37 | Assert.Equal("B", (string)Engine.ExecuteScript("s")); 38 | Assert.True((bool)Engine.ExecuteScript("delete s")); 39 | } 40 | 41 | [Fact(DisplayName = "12.14 The try Statement -> Try-Catch-Finally")] 42 | public void Test1214C() 43 | { 44 | const string script = @" 45 | var s = 'A'; 46 | try { 47 | throw 'B'; 48 | } catch (e) { 49 | s += e; 50 | } finally { 51 | s += 'C'; 52 | } 53 | return s; 54 | "; 55 | Assert.Equal("ABC", (string)Engine.ExecuteScript(script)); 56 | Assert.True((bool)Engine.ExecuteScript("delete s")); 57 | } 58 | } 59 | } -------------------------------------------------------------------------------- /Machete.Tests/Standard Built-in ECMAScript Objects/BooleanObjects.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Xunit; 3 | 4 | namespace Machete.Tests 5 | { 6 | public class BooleanObjects : TestBase 7 | { 8 | [Fact(DisplayName = "15.6.1.1 Boolean (value)")] 9 | public void Test15611() 10 | { 11 | Assert.Equal("boolean", (string)Engine.ExecuteScript("typeof Boolean(true)")); 12 | } 13 | 14 | [Fact(DisplayName = "15.6.2.1 new Boolean (value)")] 15 | public void Test15621() 16 | { 17 | Assert.IsNotType(Engine.ExecuteScript("var o = new Boolean(true);")); 18 | Assert.Equal("object", (string)Engine.ExecuteScript("typeof o")); 19 | Assert.True((bool)Engine.ExecuteScript("!!o")); 20 | Assert.True((bool)Engine.ExecuteScript("delete o")); 21 | } 22 | 23 | [Fact(DisplayName = "15.6.3.1 Boolean.prototype")] 24 | public void Test15631() 25 | { 26 | Assert.Equal("object", (string)Engine.ExecuteScript("typeof Boolean.prototype")); 27 | } 28 | 29 | [Fact(DisplayName = "15.6.4.1 Boolean.prototype.constructor")] 30 | public void Test15641() 31 | { 32 | Assert.True((bool)Engine.ExecuteScript("Boolean.prototype.constructor === Boolean")); 33 | } 34 | 35 | [Fact(DisplayName = "15.6.4.2 Boolean.prototype.toString ( )")] 36 | public void Test15642() 37 | { 38 | Assert.Equal("true", (string)Engine.ExecuteScript("(new Boolean(true)).toString()")); 39 | Assert.Equal("false", (string)Engine.ExecuteScript("(new Boolean(false)).toString()")); 40 | } 41 | 42 | [Fact(DisplayName = "15.6.4.3 Boolean.prototype.valueOf ( )")] 43 | public void Test15643() 44 | { 45 | Assert.True((bool)Engine.ExecuteScript("(new Boolean(true)).valueOf()")); 46 | Assert.False((bool)Engine.ExecuteScript("(new Boolean(false)).valueOf()")); 47 | } 48 | } 49 | } -------------------------------------------------------------------------------- /Machete.Runtime/RuntimeTypes/SpecificationTypes/SPropertyDescriptor.cs: -------------------------------------------------------------------------------- 1 | using System.Diagnostics; 2 | using Machete.Core; 3 | 4 | namespace Machete.Runtime.RuntimeTypes.SpecificationTypes 5 | { 6 | [DebuggerStepThrough] 7 | public sealed class SPropertyDescriptor : IPropertyDescriptor 8 | { 9 | public IDynamic Value { get; set; } 10 | public bool? Writable { get; set; } 11 | public IDynamic Get { get; set; } 12 | public IDynamic Set { get; set; } 13 | public bool? Enumerable { get; set; } 14 | public bool? Configurable { get; set; } 15 | 16 | public bool IsAccessorDescriptor 17 | { 18 | get { return !(Get == null && Set == null); } 19 | } 20 | 21 | public bool IsDataDescriptor 22 | { 23 | get { return !(Value == null && Writable == null); } 24 | } 25 | 26 | public bool IsGenericDescriptor 27 | { 28 | get { return !IsAccessorDescriptor && !IsDataDescriptor; } 29 | } 30 | 31 | public bool IsEmpty 32 | { 33 | get { return Value == null && Writable == null && Get == null && Set == null && Enumerable == null && Configurable == null; } 34 | } 35 | 36 | 37 | public IPropertyDescriptor Copy() 38 | { 39 | return new SPropertyDescriptor() 40 | { 41 | Value = Value, 42 | Writable = Writable, 43 | Get = Get, 44 | Set = Set, 45 | Enumerable = Enumerable, 46 | Configurable = Configurable 47 | }; 48 | } 49 | 50 | public bool Equals(IPropertyDescriptor other) 51 | { 52 | return Value == other.Value 53 | && Writable == other.Writable 54 | && Get == other.Get 55 | && Set == other.Set 56 | && Enumerable == other.Enumerable 57 | && Configurable == other.Configurable; 58 | } 59 | } 60 | } -------------------------------------------------------------------------------- /Machete.Runtime/HostObjects/Iterables/HGeneratorIterator.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using Machete.Runtime.RuntimeTypes.LanguageTypes; 6 | using Machete.Core.Generators; 7 | using Machete.Core; 8 | using Machete.Runtime.NativeObjects.BuiltinObjects; 9 | 10 | namespace Machete.Runtime.HostObjects.Iterables 11 | { 12 | public sealed class HGeneratorIterator : HIteratorBase 13 | { 14 | public Generator Generator { get; private set; } 15 | public ReadOnlyList VariableDeclarations { get; private set; } 16 | public ILexicalEnvironment Scope { get; private set; } 17 | 18 | public HGeneratorIterator(IEnvironment environment, Generator generator, ReadOnlyList variableDeclarations, ILexicalEnvironment scope) 19 | : base(environment) 20 | { 21 | Generator = generator; 22 | VariableDeclarations = variableDeclarations; 23 | Scope = scope; 24 | } 25 | 26 | public override IDynamic Current(IEnvironment environment, IArgs args) 27 | { 28 | if (!Generator.Initialized) 29 | throw environment.CreateTypeError(""); 30 | return Generator.Current; 31 | } 32 | 33 | public override IDynamic Next(IEnvironment environment, IArgs args) 34 | { 35 | if (Generator.Complete) 36 | return environment.CreateBoolean(false); 37 | environment.Context.LexicalEnviroment = Scope; 38 | environment.Context.VariableEnviroment = Scope; 39 | if (!Generator.Initialized) 40 | { 41 | environment.BindVariableDeclarations(VariableDeclarations, true, true); 42 | Generator.Initialized = true; 43 | } 44 | var step = Generator.Steps.Dequeue(); 45 | var iterated = step(environment, Generator); 46 | Generator.Complete = !iterated || Generator.Steps.Count == 0; 47 | return environment.CreateBoolean(iterated); 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /Machete.Compiler/IntParser.fs: -------------------------------------------------------------------------------- 1 | namespace Machete.Compiler 2 | 3 | open System 4 | 5 | module IntParser = 6 | 7 | let inline private isStrWhiteSpace c = 8 | CharSets.isWhiteSpace c || CharSets.isLineTerminator c 9 | 10 | let rec private passLeadingWhiteSpaceAndSign (text:string) (index:int) = 11 | if index > text.Length then -1, 1 12 | elif not (isStrWhiteSpace (text.[index])) then 13 | if text.[index] = '-' then index + 1, -1 14 | else index, 1 15 | else passLeadingWhiteSpaceAndSign text (index + 1) 16 | 17 | let private hasHexPrefix (text:string) = 18 | text.StartsWith "0x" || text.StartsWith "0X" 19 | 20 | let private getActualRadixAndStripPrefix (text:string) (radix:int) = 21 | if radix = 0 then 22 | if hasHexPrefix text 23 | then 16, true 24 | else 10, false 25 | else radix, radix = 16 && hasHexPrefix text 26 | 27 | let inline private isRadixChar (radix:int) (c:char) = 28 | if c >= '0' && c <= '9' then int c - 48 < radix 29 | elif c >= 'A' && c <= 'Z' then int c - 55 < radix 30 | elif c >= 'a' && c <= 'z' then int c - 87 < radix 31 | else false 32 | 33 | let private getRadixValue (c:char) = 34 | if c >= '0' && c <= '9' then double c - 48.0 35 | elif c >= 'A' && c <= 'Z' then double c - 55.0 36 | else double c - 87.0 37 | 38 | let rec private calculate (radix:double) (chars:list) (index:double) (result:double) = 39 | if chars.IsEmpty then result else 40 | let result = (result + ((getRadixValue chars.Head) * (radix ** index))) 41 | calculate radix chars.Tail (index + 1.0) result 42 | 43 | let Parse (text:string) (radix:int) = 44 | let startIndex, sign = passLeadingWhiteSpaceAndSign text 0 45 | let text = if startIndex > 0 then text.Substring startIndex else text 46 | let actualRadix, stripPrefix = getActualRadixAndStripPrefix text radix 47 | let text = if stripPrefix then text.Substring 2 else text 48 | let chars = text |> Seq.takeWhile (isRadixChar actualRadix) |> Seq.toList |> List.rev 49 | if chars.IsEmpty 50 | then Double.NaN 51 | else calculate (actualRadix |> double) chars 0.0 0.0 -------------------------------------------------------------------------------- /Machete.Runtime/RuntimeTypes/LanguageTypes/LNull.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using Machete.Runtime.RuntimeTypes.SpecificationTypes; 6 | using Machete.Core; 7 | 8 | namespace Machete.Runtime.RuntimeTypes.LanguageTypes 9 | { 10 | public sealed class LNull : LType, INull 11 | { 12 | public override LanguageTypeCode TypeCode 13 | { 14 | get { return LanguageTypeCode.Null; } 15 | } 16 | 17 | public override bool IsPrimitive 18 | { 19 | get { return true; } 20 | } 21 | 22 | public LNull(IEnvironment environment) 23 | : base(environment) 24 | { 25 | 26 | } 27 | 28 | public override IDynamic Op_Equals(IDynamic other) 29 | { 30 | switch (other.TypeCode) 31 | { 32 | case LanguageTypeCode.Null: 33 | case LanguageTypeCode.Undefined: 34 | return Environment.True; 35 | default: 36 | return Environment.False; 37 | } 38 | } 39 | 40 | public override IDynamic Op_StrictEquals(IDynamic other) 41 | { 42 | switch (other.TypeCode) 43 | { 44 | case LanguageTypeCode.Null: 45 | return Environment.True; 46 | default: 47 | return Environment.False; 48 | } 49 | } 50 | 51 | public override IDynamic Op_Typeof() 52 | { 53 | return Environment.CreateString("object"); 54 | } 55 | 56 | public override IDynamic ConvertToPrimitive(string preferredType) 57 | { 58 | return this; 59 | } 60 | 61 | public override IBoolean ConvertToBoolean() 62 | { 63 | return Environment.False; 64 | } 65 | 66 | public override INumber ConvertToNumber() 67 | { 68 | return Environment.CreateNumber(0); 69 | } 70 | 71 | public override IString ConvertToString() 72 | { 73 | return Environment.CreateString("null"); 74 | } 75 | 76 | public override IObject ConvertToObject() 77 | { 78 | throw Environment.CreateTypeError(""); 79 | } 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /Machete.Runtime/RuntimeTypes/SpecificationTypes/SArgs.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using Machete.Runtime.RuntimeTypes.LanguageTypes; 6 | using System.Diagnostics; 7 | using Machete.Core; 8 | using System.Collections; 9 | 10 | namespace Machete.Runtime.RuntimeTypes.SpecificationTypes 11 | { 12 | public sealed class SArgs : IArgs 13 | { 14 | private readonly IEnvironment _environment; 15 | private readonly IDynamic[] _items; 16 | 17 | 18 | public SArgs(IEnvironment environment, params IDynamic[] items) 19 | { 20 | _environment = environment; 21 | _items = items; 22 | } 23 | 24 | public SArgs(IEnvironment environment, IEnumerable items) 25 | { 26 | _environment = environment; 27 | _items = items as IDynamic[]; 28 | if (_items == null) 29 | { 30 | _items = items.ToArray(); 31 | } 32 | } 33 | 34 | public SArgs(IEnvironment environment, IArgs head, IArgs tail) 35 | { 36 | _environment = environment; 37 | _items = head.Concat(tail).ToArray(); 38 | } 39 | 40 | public SArgs(IEnvironment environment, IArgs head, params IDynamic[] items) 41 | { 42 | _environment = environment; 43 | _items = head.Concat(items).ToArray(); 44 | } 45 | 46 | 47 | public IDynamic this[int index] 48 | { 49 | get 50 | { 51 | Debug.Assert(index >= 0); 52 | if (index > _items.Length - 1) 53 | { 54 | return _environment.Undefined; 55 | } 56 | return _items[index]; 57 | } 58 | } 59 | 60 | public int Count 61 | { 62 | get { return _items.Length; } 63 | } 64 | 65 | public bool IsEmpty 66 | { 67 | get { return _items.Length == 0; } 68 | } 69 | 70 | 71 | public IEnumerator GetEnumerator() 72 | { 73 | return _items.Cast().GetEnumerator(); 74 | } 75 | 76 | IEnumerator IEnumerable.GetEnumerator() 77 | { 78 | return _items.GetEnumerator(); 79 | } 80 | } 81 | } -------------------------------------------------------------------------------- /Machete.Runtime/NativeObjects/BuiltinObjects/CString.cs: -------------------------------------------------------------------------------- 1 | using Machete.Core; 2 | using Machete.Runtime.RuntimeTypes.LanguageTypes; 3 | using System.Text; 4 | 5 | namespace Machete.Runtime.NativeObjects.BuiltinObjects.ConstructorObjects 6 | { 7 | public sealed class CString : BConstructor 8 | { 9 | public CString(IEnvironment environment) 10 | : base(environment) 11 | { 12 | 13 | } 14 | 15 | public sealed override void Initialize() 16 | { 17 | base.Initialize(); 18 | DefineOwnProperty("length", Environment.CreateDataDescriptor(Environment.CreateNumber(1.0), false, false, false), false); 19 | DefineOwnProperty("prototype", Environment.CreateDataDescriptor(Environment.StringPrototype, false, false, false), false); 20 | } 21 | 22 | protected sealed override IDynamic Call(IEnvironment environment, IArgs args) 23 | { 24 | if (args.Count > 0) 25 | { 26 | return args[0].ConvertToString(); 27 | } 28 | return environment.CreateString(""); 29 | } 30 | 31 | public sealed override IObject Construct(IEnvironment environment, IArgs args) 32 | { 33 | var obj = new NString(environment); 34 | { 35 | var str = args.Count > 0 ? args[0].ConvertToString() : environment.CreateString(""); 36 | var len = environment.CreateNumber(str.BaseValue.Length); 37 | var lenDesc = environment.CreateDataDescriptor(len, false, false, false); 38 | 39 | obj.Class = "String"; 40 | obj.Extensible = true; 41 | obj.Prototype = environment.StringPrototype; 42 | obj.PrimitiveValue = str; 43 | obj.DefineOwnProperty("length", lenDesc, false); 44 | } 45 | return obj; 46 | } 47 | 48 | [BuiltinFunction("fromCharCode", "char0"), DataDescriptor(true, false, true)] 49 | internal static IDynamic FromCharCode(IEnvironment environment, IArgs args) 50 | { 51 | var sb = new StringBuilder(args.Count); 52 | foreach (var arg in args) 53 | { 54 | sb.Append((char)arg.ConvertToUInt16().BaseValue); 55 | } 56 | return environment.CreateString(sb.ToString()); 57 | } 58 | } 59 | } -------------------------------------------------------------------------------- /Machete.Core/IDynamic.cs: -------------------------------------------------------------------------------- 1 | using System.Dynamic; 2 | namespace Machete.Core 3 | { 4 | public interface IDynamic 5 | { 6 | LanguageTypeCode TypeCode { get; } 7 | bool IsPrimitive { get; } 8 | IDynamic Value { get; set; } 9 | 10 | IDynamic Op_LogicalNot(); 11 | IDynamic Op_LogicalOr(IDynamic other); 12 | IDynamic Op_LogicalAnd(IDynamic other); 13 | 14 | IDynamic Op_BitwiseNot(); 15 | IDynamic Op_BitwiseOr(IDynamic other); 16 | IDynamic Op_BitwiseXor(IDynamic other); 17 | IDynamic Op_BitwiseAnd(IDynamic other); 18 | 19 | IDynamic Op_Equals(IDynamic other); 20 | IDynamic Op_DoesNotEquals(IDynamic other); 21 | IDynamic Op_StrictEquals(IDynamic other); 22 | IDynamic Op_StrictDoesNotEquals(IDynamic other); 23 | 24 | IDynamic Op_Lessthan(IDynamic other); 25 | IDynamic Op_Greaterthan(IDynamic other); 26 | IDynamic Op_LessthanOrEqual(IDynamic other); 27 | IDynamic Op_GreaterthanOrEqual(IDynamic other); 28 | IDynamic Op_Instanceof(IDynamic other); 29 | IDynamic Op_In(IDynamic other); 30 | 31 | IDynamic Op_LeftShift(IDynamic other); 32 | IDynamic Op_SignedRightShift(IDynamic other); 33 | IDynamic Op_UnsignedRightShift(IDynamic other); 34 | 35 | IDynamic Op_Addition(IDynamic other); 36 | IDynamic Op_Subtraction(IDynamic other); 37 | IDynamic Op_Multiplication(IDynamic other); 38 | IDynamic Op_Division(IDynamic other); 39 | IDynamic Op_Modulus(IDynamic other); 40 | IDynamic Op_Delete(); 41 | IDynamic Op_Void(); 42 | IDynamic Op_Typeof(); 43 | IDynamic Op_PrefixIncrement(); 44 | IDynamic Op_PrefixDecrement(); 45 | IDynamic Op_Plus(); 46 | IDynamic Op_Minus(); 47 | IDynamic Op_PostfixIncrement(); 48 | IDynamic Op_PostfixDecrement(); 49 | 50 | IDynamic Op_Call(IArgs args); 51 | IObject Op_Construct(IArgs args); 52 | void Op_Throw(); 53 | 54 | IDynamic ConvertToPrimitive(string preferredType); 55 | IBoolean ConvertToBoolean(); 56 | INumber ConvertToNumber(); 57 | IString ConvertToString(); 58 | IObject ConvertToObject(); 59 | INumber ConvertToInteger(); 60 | INumber ConvertToInt32(); 61 | INumber ConvertToUInt32(); 62 | INumber ConvertToUInt16(); 63 | } 64 | } -------------------------------------------------------------------------------- /Machete.Runtime/RuntimeTypes/SpecificationTypes/SLexicalEnvironment.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using Machete.Runtime.RuntimeTypes.LanguageTypes; 6 | using System.Diagnostics; 7 | using Machete.Core; 8 | 9 | namespace Machete.Runtime.RuntimeTypes.SpecificationTypes 10 | { 11 | public sealed class SLexicalEnvironment : ILexicalEnvironment 12 | { 13 | private readonly IEnvironment _environment; 14 | public IEnvironmentRecord Record { get; set; } 15 | public ILexicalEnvironment Parent { get; set; } 16 | 17 | 18 | public SLexicalEnvironment(IEnvironment environment, IEnvironmentRecord record, ILexicalEnvironment parent) 19 | { 20 | _environment = environment; 21 | Record = record; 22 | Parent = parent; 23 | } 24 | 25 | public IReference GetIdentifierReference(string name, bool strict) 26 | { 27 | if (Record.HasBinding(name)) 28 | { 29 | return _environment.CreateReference(name, Record, strict); 30 | } 31 | else if (Parent == null) 32 | { 33 | return _environment.CreateReference(name, _environment.Undefined, strict); 34 | } 35 | else 36 | { 37 | return Parent.GetIdentifierReference(name, strict); 38 | } 39 | } 40 | 41 | public SLexicalEnvironment NewDeclarativeEnvironment() 42 | { 43 | return new SLexicalEnvironment(_environment, new SDeclarativeEnvironmentRecord(_environment), this); 44 | } 45 | 46 | public SLexicalEnvironment NewObjectEnvironment(LObject o) 47 | { 48 | Debug.Assert(o != null); 49 | return new SLexicalEnvironment(_environment, new SDeclarativeEnvironmentRecord(_environment), this); 50 | } 51 | 52 | 53 | ILexicalEnvironment ILexicalEnvironment.NewDeclarativeEnvironment() 54 | { 55 | return new SLexicalEnvironment(_environment, new SDeclarativeEnvironmentRecord(_environment), this); 56 | } 57 | 58 | 59 | public ILexicalEnvironment NewObjectEnvironment(IObject bindingObject, bool provideThis) 60 | { 61 | return new SLexicalEnvironment(_environment, new SObjectEnvironmentRecord(_environment, bindingObject, provideThis), this); 62 | } 63 | } 64 | } -------------------------------------------------------------------------------- /Machete.Runtime/NativeObjects/BuiltinObjects/CNumber.cs: -------------------------------------------------------------------------------- 1 | using Machete.Core; 2 | using Machete.Runtime.RuntimeTypes.LanguageTypes; 3 | 4 | namespace Machete.Runtime.NativeObjects.BuiltinObjects.ConstructorObjects 5 | { 6 | public sealed class CNumber : BConstructor 7 | { 8 | public CNumber(IEnvironment environment) 9 | : base(environment) 10 | { 11 | 12 | } 13 | 14 | public sealed override void Initialize() 15 | { 16 | base.Initialize(); 17 | DefineOwnProperty("length", Environment.CreateDataDescriptor(Environment.CreateNumber(1.0), false, false, false), false); 18 | DefineOwnProperty("prototype", Environment.CreateDataDescriptor(Environment.NumberPrototype, false, false, false), false); 19 | DefineOwnProperty("MAX_VALUE", Environment.CreateDataDescriptor(Environment.CreateNumber(double.MaxValue), false, false, false), false); 20 | DefineOwnProperty("MIN_VALUE", Environment.CreateDataDescriptor(Environment.CreateNumber(double.MinValue), false, false, false), false); 21 | DefineOwnProperty("NaN", Environment.CreateDataDescriptor(Environment.CreateNumber(double.NaN), false, false, false), false); 22 | DefineOwnProperty("NEGATIVE_INFINITY", Environment.CreateDataDescriptor(Environment.CreateNumber(double.NegativeInfinity), false, false, false), false); 23 | DefineOwnProperty("POSITIVE_INFINITY", Environment.CreateDataDescriptor(Environment.CreateNumber(double.PositiveInfinity), false, false, false), false); 24 | } 25 | 26 | protected sealed override IDynamic Call(IEnvironment environment, IArgs args) 27 | { 28 | if (args.Count > 0) 29 | { 30 | return args[0].ConvertToNumber(); 31 | } 32 | return environment.CreateNumber(0.0); 33 | } 34 | 35 | public sealed override IObject Construct(IEnvironment environment, IArgs args) 36 | { 37 | var obj = new NNumber(environment); 38 | obj.Class = "Number"; 39 | obj.Extensible = true; 40 | obj.Prototype = environment.NumberPrototype; 41 | if (args.Count > 0) 42 | { 43 | obj.PrimitiveValue = args[0].ConvertToNumber(); 44 | } 45 | else 46 | { 47 | obj.PrimitiveValue = environment.CreateNumber(0.0); 48 | } 49 | return obj; 50 | } 51 | } 52 | } -------------------------------------------------------------------------------- /Machete.Runtime/NativeObjects/BuiltinObjects/CFunction.cs: -------------------------------------------------------------------------------- 1 | using Machete.Core; 2 | using Machete.Runtime.RuntimeTypes.LanguageTypes; 3 | using System.Text; 4 | using Machete.Compiler; 5 | 6 | namespace Machete.Runtime.NativeObjects.BuiltinObjects.ConstructorObjects 7 | { 8 | public sealed class CFunction : BConstructor 9 | { 10 | public CFunction(IEnvironment environment) 11 | : base(environment) 12 | { 13 | 14 | } 15 | 16 | public sealed override void Initialize() 17 | { 18 | base.Initialize(); 19 | DefineOwnProperty("length", Environment.CreateDataDescriptor(Environment.CreateNumber(1.0), false, false, false), false); 20 | DefineOwnProperty("prototype", Environment.CreateDataDescriptor(Environment.FunctionPrototype, false, false, false), false); 21 | } 22 | 23 | protected sealed override IDynamic Call(IEnvironment environment, IArgs args) 24 | { 25 | return Construct(environment, args); 26 | } 27 | 28 | public override IObject Construct(IEnvironment environment, IArgs args) 29 | { 30 | string formalParametersString, functionBody; 31 | 32 | if (args.IsEmpty) 33 | { 34 | formalParametersString = ""; 35 | functionBody = ""; 36 | } 37 | else if (args.Count == 1) 38 | { 39 | formalParametersString = ""; 40 | functionBody = args[0].ConvertToString().BaseValue; 41 | } 42 | else 43 | { 44 | var sb = new StringBuilder(); 45 | var limit = args.Count - 1; 46 | for (int i = 0; i < limit; i++) 47 | { 48 | if (sb.Length > 0) 49 | { 50 | sb.Append(","); 51 | } 52 | sb.Append(args[i].ConvertToString().BaseValue); 53 | } 54 | formalParametersString = sb.ToString(); 55 | functionBody = args[limit].ConvertToString().BaseValue; 56 | } 57 | 58 | var compiler = new CompilerService(environment); 59 | var executableCode = compiler.CompileFunctionCode(functionBody, environment.Context.Strict); 60 | var formalParameters = compiler.CompileFormalParameterList(formalParametersString); 61 | var func = environment.CreateFunction(executableCode, formalParameters, environment.GlobalEnvironment); 62 | return func; 63 | } 64 | } 65 | } -------------------------------------------------------------------------------- /Machete.Tests/Expressions/UnaryOperators.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Xunit; 3 | 4 | namespace Machete.Tests 5 | { 6 | public class UnaryOperators : TestBase 7 | { 8 | [Fact(DisplayName = "11.4.1 The delete Operator")] 9 | public void Test1141() 10 | { 11 | Assert.True((bool)Engine.ExecuteScript("delete 2")); 12 | Assert.True((bool)Engine.ExecuteScript("var o = {}; delete o")); 13 | } 14 | 15 | [Fact(DisplayName = "11.4.2 The void Operator")] 16 | public void Test1142() 17 | { 18 | Assert.Equal("undefined", (string)Engine.ExecuteScript("typeof (void 1)")); 19 | } 20 | 21 | [Fact(DisplayName = "11.4.3 The typeof Operator")] 22 | public void Test1143() 23 | { 24 | Assert.Equal("undefined", (string)Engine.ExecuteScript("typeof undefined")); 25 | Assert.Equal("object", (string)Engine.ExecuteScript("typeof null")); 26 | Assert.Equal("boolean", (string)Engine.ExecuteScript("typeof true")); 27 | Assert.Equal("number", (string)Engine.ExecuteScript("typeof 0")); 28 | Assert.Equal("string", (string)Engine.ExecuteScript("typeof ''")); 29 | Assert.Equal("object", (string)Engine.ExecuteScript("typeof ({})")); 30 | Assert.Equal("function", (string)Engine.ExecuteScript("typeof function(){}")); 31 | } 32 | 33 | [Fact(DisplayName = "11.4.4 Prefix Increment Operator")] 34 | public void Test1144() 35 | { 36 | Assert.Equal(2.0, (double)Engine.ExecuteScript("var x = 1; ++x;")); 37 | } 38 | 39 | [Fact(DisplayName = "11.4.5 Prefix Decrement Operator")] 40 | public void Test1145() 41 | { 42 | Assert.Equal(2.0, (double)Engine.ExecuteScript("var x = 3; --x;")); 43 | } 44 | 45 | [Fact(DisplayName = "11.4.6 Unary + Operator")] 46 | public void Test1146() 47 | { 48 | Assert.Equal(1.0, (double)Engine.ExecuteScript("+true")); 49 | } 50 | 51 | [Fact(DisplayName = "11.4.7 Unary - Operator")] 52 | public void Test1147() 53 | { 54 | Assert.Equal(-1.0, (double)Engine.ExecuteScript("-1")); 55 | } 56 | 57 | [Fact(DisplayName = "11.4.8 Bitwise NOT Operator ( ~ )")] 58 | public void Test1148() 59 | { 60 | Assert.Equal(~16, (double)Engine.ExecuteScript("~16")); 61 | } 62 | 63 | [Fact(DisplayName = "11.4.9 Logical NOT Operator ( ! )")] 64 | public void Test1149() 65 | { 66 | Assert.True((bool)Engine.ExecuteScript("!false")); 67 | } 68 | } 69 | } -------------------------------------------------------------------------------- /Machete.Runtime/RuntimeTypes/LanguageTypes/LUndefined.cs: -------------------------------------------------------------------------------- 1 | using Machete.Core; 2 | 3 | namespace Machete.Runtime.RuntimeTypes.LanguageTypes 4 | { 5 | public sealed class LUndefined : LType, IUndefined 6 | { 7 | public override LanguageTypeCode TypeCode 8 | { 9 | get { return LanguageTypeCode.Undefined; } 10 | } 11 | 12 | public override bool IsPrimitive 13 | { 14 | get { return true; } 15 | } 16 | 17 | public LUndefined(IEnvironment environment) 18 | : base(environment) 19 | { 20 | 21 | } 22 | 23 | public override IDynamic Op_Equals(IDynamic other) 24 | { 25 | switch (other.TypeCode) 26 | { 27 | case LanguageTypeCode.Null: 28 | case LanguageTypeCode.Undefined: 29 | return Environment.True; 30 | default: 31 | return Environment.False; 32 | } 33 | } 34 | 35 | public override IDynamic Op_StrictEquals(IDynamic other) 36 | { 37 | switch (other.TypeCode) 38 | { 39 | case LanguageTypeCode.Undefined: 40 | return Environment.True; 41 | default: 42 | return Environment.False; 43 | } 44 | } 45 | 46 | public override IDynamic Op_Typeof() 47 | { 48 | return Environment.CreateString("undefined"); 49 | } 50 | 51 | public override IDynamic ConvertToPrimitive(string preferredType) 52 | { 53 | return this; 54 | } 55 | 56 | public override IBoolean ConvertToBoolean() 57 | { 58 | return Environment.False; 59 | } 60 | 61 | public override INumber ConvertToNumber() 62 | { 63 | return Environment.CreateNumber(0); 64 | } 65 | 66 | public override IString ConvertToString() 67 | { 68 | return Environment.CreateString("undefined"); 69 | } 70 | 71 | public override IObject ConvertToObject() 72 | { 73 | throw Environment.CreateTypeError(""); 74 | } 75 | 76 | public IDynamic Get(string name, bool strict) 77 | { 78 | throw Environment.CreateReferenceError("The name '" + name + "' could not be resolved."); 79 | } 80 | 81 | public void Set(string name, IDynamic value, bool strict) 82 | { 83 | if (strict) throw Environment.CreateReferenceError("The name '" + name + "' could not be resolved."); 84 | Environment.GlobalObject.Put(name, value, strict); 85 | } 86 | } 87 | } -------------------------------------------------------------------------------- /Machete.Runtime/RuntimeTypes/LanguageTypes/LBoolean.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using Machete.Runtime.RuntimeTypes.SpecificationTypes; 6 | using Machete.Runtime.NativeObjects; 7 | using Machete.Core; 8 | 9 | namespace Machete.Runtime.RuntimeTypes.LanguageTypes 10 | { 11 | public sealed class LBoolean : LType, IBoolean 12 | { 13 | public bool BaseValue { get; private set; } 14 | 15 | public override LanguageTypeCode TypeCode 16 | { 17 | get { return LanguageTypeCode.Boolean; } 18 | } 19 | 20 | public override bool IsPrimitive 21 | { 22 | get { return true; } 23 | } 24 | 25 | public LBoolean(IEnvironment environment, bool value) 26 | : base(environment) 27 | { 28 | BaseValue = value; 29 | } 30 | 31 | public override IDynamic Op_Equals(IDynamic other) 32 | { 33 | switch (other.TypeCode) 34 | { 35 | case LanguageTypeCode.Boolean: 36 | return Environment.CreateBoolean(this.BaseValue == ((LBoolean)other).BaseValue); 37 | default: 38 | return this.ConvertToNumber().Op_Equals(other); 39 | } 40 | } 41 | 42 | public override IDynamic Op_StrictEquals(IDynamic other) 43 | { 44 | switch (other.TypeCode) 45 | { 46 | case LanguageTypeCode.Boolean: 47 | return Environment.CreateBoolean(this.BaseValue == ((LBoolean)other).BaseValue); 48 | default: 49 | return Environment.CreateBoolean(false); 50 | } 51 | } 52 | 53 | public override IDynamic Op_Typeof() 54 | { 55 | return Environment.CreateString("boolean"); 56 | } 57 | 58 | public override IDynamic ConvertToPrimitive(string preferredType) 59 | { 60 | return this; 61 | } 62 | 63 | public override IBoolean ConvertToBoolean() 64 | { 65 | return this; 66 | } 67 | 68 | public override INumber ConvertToNumber() 69 | { 70 | return BaseValue ? Environment.CreateNumber(1) : Environment.CreateNumber(0); 71 | } 72 | 73 | public override IString ConvertToString() 74 | { 75 | return BaseValue ? Environment.CreateString("true") : Environment.CreateString("false"); 76 | } 77 | 78 | public override IObject ConvertToObject() 79 | { 80 | return ((IConstructable)Environment.BooleanConstructor).Construct(Environment, Environment.CreateArgs(new IDynamic[] { this })); 81 | } 82 | } 83 | } -------------------------------------------------------------------------------- /Machete.Tests/Lexical Conventions/StringLiteral.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Xunit; 3 | using Machete.Core; 4 | 5 | namespace Machete.Tests 6 | { 7 | public sealed class StringLiteral : TestBase 8 | { 9 | [Fact(DisplayName = "07.8.4 String Literals: Simple")] 10 | public void Test0784A() 11 | { 12 | Assert.Equal("test", (string)Engine.ExecuteScript("\"test\"")); 13 | Assert.Equal("test", (string)Engine.ExecuteScript("'test'")); 14 | } 15 | 16 | [Fact(DisplayName = "07.8.4 String Literals: LineContinuation")] 17 | public void Test0784B() 18 | { 19 | Assert.Equal("", (string)Engine.ExecuteScript("\"\\\r\"")); 20 | Assert.Equal("", (string)Engine.ExecuteScript("'\\\r'")); 21 | } 22 | 23 | [Fact(DisplayName = "07.8.4 String Literals: '\\0'")] 24 | public void Test0784C() 25 | { 26 | Assert.Equal("\u0000", (string)Engine.ExecuteScript("\"\\0\"")); 27 | Assert.Equal("\u0000", (string)Engine.ExecuteScript("'\\0'")); 28 | } 29 | 30 | [Fact(DisplayName = "07.8.4 String Literals: SingleEscapeCharacter")] 31 | public void Test0784D() 32 | { 33 | Assert.Equal("'\"\\\b\f\n\r\t\v", (string)Engine.ExecuteScript("\"\\'\\\"\\\\\\b\\f\\n\\r\\t\\v\"")); 34 | Assert.Equal("'\"\\\b\f\n\r\t\v", (string)Engine.ExecuteScript("'\\'\\\"\\\\\\b\\f\\n\\r\\t\\v'")); 35 | } 36 | 37 | [Fact(DisplayName = "07.8.4 String Literals: HexEscapeSequence")] 38 | public void Test0784E() 39 | { 40 | Assert.Equal("\u0001", (string)Engine.ExecuteScript("\"\\x01\"")); 41 | Assert.Equal("\u0001", (string)Engine.ExecuteScript("'\\x01'")); 42 | Assert.Equal("\u00AF", (string)Engine.ExecuteScript("\"\\xAF\"")); 43 | Assert.Equal("\u00AF", (string)Engine.ExecuteScript("'\\xAF'")); 44 | } 45 | 46 | [Fact(DisplayName = "07.8.4 String Literals: UnicodeEscapeSequence")] 47 | public void Test0784F() 48 | { 49 | Assert.Equal("\u000A", (string)Engine.ExecuteScript("\"\\u000A\"")); 50 | Assert.Equal("\u000A", (string)Engine.ExecuteScript("'\\u000A'")); 51 | Assert.Equal("\u100f", (string)Engine.ExecuteScript("\"\\u100f\"")); 52 | Assert.Equal("\u100f", (string)Engine.ExecuteScript("'\\u100f'")); 53 | } 54 | 55 | [Fact(DisplayName = "07.8.4 String Literals: Cannot Contain LineTerminator")] 56 | public void Test0784G() 57 | { 58 | Assert.IsAssignableFrom(Engine.ExecuteScript("\"\n\"")); 59 | Assert.IsAssignableFrom(Engine.ExecuteScript("'\n'")); 60 | } 61 | } 62 | } -------------------------------------------------------------------------------- /Machete.Tests/Lexical Conventions/WhiteSpace.cs: -------------------------------------------------------------------------------- 1 | using System.Globalization; 2 | using Machete.Core; 3 | using Xunit; 4 | 5 | namespace Machete.Tests.Lexical_Conventions 6 | { 7 | public sealed class WhiteSpace : TestBase 8 | { 9 | //[Fact(DisplayName = "07.02 White Space: TAB")] 10 | //public void Test0702A() 11 | //{ 12 | // var r = Engine.ExecuteScriptToDynamic("\u00092"); 13 | // Assert.IsAssignableFrom(r); 14 | // Assert.Equal(2.0, ((INumber)r).BaseValue); 15 | //} 16 | 17 | //[Fact(DisplayName = "07.02 White Space: VT")] 18 | //public void Test0702B() 19 | //{ 20 | // var r = Engine.ExecuteScriptToDynamic("\u000B2"); 21 | // Assert.IsAssignableFrom(r); 22 | // Assert.Equal(2.0, ((INumber)r).BaseValue); 23 | //} 24 | 25 | //[Fact(DisplayName = "07.02 White Space: FF")] 26 | //public void Test0702C() 27 | //{ 28 | // var r = Engine.ExecuteScriptToDynamic("\u000C2"); 29 | // Assert.IsAssignableFrom(r); 30 | // Assert.Equal(2.0, ((INumber)r).BaseValue); 31 | //} 32 | 33 | //[Fact(DisplayName = "07.02 White Space: SP")] 34 | //public void Test0702D() 35 | //{ 36 | // var r = Engine.ExecuteScriptToDynamic("\u00202"); 37 | // Assert.IsAssignableFrom(r); 38 | // Assert.Equal(2.0, ((INumber)r).BaseValue); 39 | //} 40 | 41 | //[Fact(DisplayName = "07.02 White Space: NBSP")] 42 | //public void Test0702E() 43 | //{ 44 | // var r = Engine.ExecuteScriptToDynamic("\u00A02"); 45 | // Assert.IsAssignableFrom(r); 46 | // Assert.Equal(2.0, ((INumber)r).BaseValue); 47 | //} 48 | 49 | //[Fact(DisplayName = "07.02 White Space: BOM")] 50 | //public void Test0702F() 51 | //{ 52 | // var r = Engine.ExecuteScriptToDynamic("\uFEFF2"); 53 | // Assert.IsAssignableFrom(r); 54 | // Assert.Equal(2.0, ((INumber)r).BaseValue); 55 | //} 56 | 57 | //[Fact(DisplayName = "07.02 White Space: USP")] 58 | //public void Test0702G() 59 | //{ 60 | // for (char c = char.MinValue; c < char.MaxValue; c++) 61 | // { 62 | // switch (char.GetUnicodeCategory(c)) 63 | // { 64 | // case UnicodeCategory.SpaceSeparator: 65 | // var r = Engine.ExecuteScriptToDynamic(c + "2"); 66 | // Assert.IsAssignableFrom(r); 67 | // Assert.Equal(2.0, ((INumber)r).BaseValue); 68 | // break; 69 | // } 70 | // } 71 | //} 72 | } 73 | } -------------------------------------------------------------------------------- /Machete.Runtime/RuntimeTypes/LanguageTypes/LString.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Machete.Runtime.NativeObjects; 3 | using Machete.Core; 4 | 5 | namespace Machete.Runtime.RuntimeTypes.LanguageTypes 6 | { 7 | public sealed class LString : LType, IString 8 | { 9 | public string BaseValue { get; private set; } 10 | 11 | public override LanguageTypeCode TypeCode 12 | { 13 | get { return LanguageTypeCode.String; } 14 | } 15 | 16 | public override bool IsPrimitive 17 | { 18 | get { return true; } 19 | } 20 | 21 | public LString(IEnvironment environment, string value) 22 | : base(environment) 23 | { 24 | BaseValue = value; 25 | } 26 | 27 | public override IDynamic Op_Equals(IDynamic other) 28 | { 29 | switch (other.TypeCode) 30 | { 31 | case LanguageTypeCode.String: 32 | return Environment.CreateBoolean(this.BaseValue == ((LString)other).BaseValue); 33 | case LanguageTypeCode.Number: 34 | return this.ConvertToNumber().Op_Equals(other); 35 | case LanguageTypeCode.Object: 36 | return this.ConvertToPrimitive(null).Op_Equals(other); 37 | default: 38 | return Environment.False; 39 | } 40 | } 41 | 42 | public override IDynamic Op_StrictEquals(IDynamic other) 43 | { 44 | switch (other.TypeCode) 45 | { 46 | case LanguageTypeCode.String: 47 | return Environment.CreateBoolean(this.BaseValue == ((LString)other).BaseValue); 48 | default: 49 | return Environment.False; 50 | } 51 | } 52 | 53 | public override IDynamic Op_Typeof() 54 | { 55 | return Environment.CreateString("string"); 56 | } 57 | 58 | public override IDynamic ConvertToPrimitive(string preferredType) 59 | { 60 | return this; 61 | } 62 | 63 | public override IBoolean ConvertToBoolean() 64 | { 65 | return Environment.CreateBoolean(BaseValue.Length > 0); 66 | } 67 | 68 | public override INumber ConvertToNumber() 69 | { 70 | return Environment.CreateNumber(Machete.Compiler.StringNumericLiteral.eval(BaseValue)); 71 | } 72 | 73 | public override IString ConvertToString() 74 | { 75 | return this; 76 | } 77 | 78 | public override IObject ConvertToObject() 79 | { 80 | return ((IConstructable)Environment.StringConstructor).Construct(Environment, Environment.CreateArgs(new IDynamic[] { this })); 81 | } 82 | } 83 | } -------------------------------------------------------------------------------- /Machete.Tests/Standard Built-in ECMAScript Objects/JsonObject.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Xunit; 3 | 4 | namespace Machete.Tests 5 | { 6 | public class JsonObject : TestBase 7 | { 8 | [Fact(DisplayName = "15.12.2 parse ( text [ , reviver ] ): JSONBooleanLiteral")] 9 | public void TestJSONBooleanLiteral() 10 | { 11 | ExpectTrue("JSON.parse('true')"); 12 | ExpectFalse("JSON.parse('false')"); 13 | } 14 | 15 | [Fact(DisplayName = "15.12.2 parse ( text [ , reviver ] ): JSONNullLiteral")] 16 | public void TestJSONNullLiteral() 17 | { 18 | ExpectTrue("JSON.parse('null') === null"); 19 | } 20 | 21 | [Fact(DisplayName = "15.12.2 parse ( text [ , reviver ] ): JSONString")] 22 | public void TestJSONString() 23 | { 24 | ExpectTrue("JSON.parse('\"string\"') === 'string'"); 25 | } 26 | 27 | [Fact(DisplayName = "15.12.2 parse ( text [ , reviver ] ): JSONNumber")] 28 | public void TestJSONNumber() 29 | { 30 | ExpectTrue("JSON.parse('-2.999e2') === -2.999e2"); 31 | } 32 | 33 | [Fact(DisplayName = "15.12.2 parse ( text [ , reviver ] ): JSONArray")] 34 | public void TestJSONArray() 35 | { 36 | ExpectString("JSON.parse('[true, false, null, -2.01, \"string\"]')", "true,false,,-2.01,string"); 37 | } 38 | 39 | [Fact(DisplayName = "15.12.2 parse ( text [ , reviver ] ): JSONObject")] 40 | public void TestJSONObject() 41 | { 42 | ExpectString(@" 43 | (function() { 44 | var o = JSON.parse('{ ""BoolTrue"": true, ""BoolFalse"": false, ""Null"": null, ""Number"": 2, ""String"": ""string"" }'); 45 | if (!o.hasOwnProperty('BoolTrue')) return 'Missing BoolTrue'; 46 | if (!o.BoolTrue) return 'BoolTrue is false'; 47 | if (!o.hasOwnProperty('BoolFalse')) return 'Missing BoolFalse'; 48 | if (o.BoolFalse) return 'BoolFalse is true'; 49 | if (!o.hasOwnProperty('Null')) return 'Missing Null'; 50 | if (o.Null !== null) return 'Null is not null'; 51 | if (!o.hasOwnProperty('Number')) return 'Missing Number'; 52 | if (o.Number !== 2) return 'Number is not 2'; 53 | if (!o.hasOwnProperty('String')) return 'Missing String'; 54 | if (o.String !== 'string') return 'String is not ""string""'; 55 | return 'Success'; 56 | })(); 57 | ", "Success"); 58 | } 59 | 60 | [Fact(DisplayName = "15.12.03 stringify ( value [ , replacer [ , space ] ] )")] 61 | public void Test151203() 62 | { 63 | Assert.True(false); 64 | } 65 | } 66 | } -------------------------------------------------------------------------------- /Machete.Runtime/RuntimeTypes/SpecificationTypes/SObjectEnvironmentRecord.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using Machete.Runtime.RuntimeTypes.LanguageTypes; 6 | using Machete.Runtime.NativeObjects.BuiltinObjects; 7 | using System.Diagnostics.Contracts; 8 | using Machete.Runtime.NativeObjects.BuiltinObjects.ConstructorObjects; 9 | using Machete.Core; 10 | 11 | namespace Machete.Runtime.RuntimeTypes.SpecificationTypes 12 | { 13 | public sealed class SObjectEnvironmentRecord : IObjectEnvironmentRecord 14 | { 15 | private readonly IEnvironment _environment; 16 | private readonly IObject _bindingObject; 17 | private readonly bool _provideThis; 18 | 19 | public SObjectEnvironmentRecord(IEnvironment environment, IObject bindingObject, bool provideThis) 20 | { 21 | _environment = environment; 22 | _bindingObject = bindingObject; 23 | _provideThis = provideThis; 24 | } 25 | 26 | public bool HasBinding(string n) 27 | { 28 | return _bindingObject.HasProperty(n); 29 | } 30 | 31 | public void CreateMutableBinding(string n, bool d) 32 | { 33 | var desc = new SPropertyDescriptor() { 34 | Value = _environment.Undefined, 35 | Writable = true, 36 | Enumerable = true, 37 | Configurable = d 38 | }; 39 | _bindingObject.DefineOwnProperty(n, desc, false); 40 | } 41 | 42 | public void SetMutableBinding(string n, IDynamic v, bool s) 43 | { 44 | Contract.Assert(n != null); 45 | Contract.Assert(v != null); 46 | _bindingObject.Put(n, v, s); 47 | } 48 | 49 | public IDynamic GetBindingValue(string n, bool s) 50 | { 51 | Contract.Assert(n != null); 52 | if (!_bindingObject.HasProperty(n)) 53 | { 54 | if (!s) return _environment.Undefined; 55 | throw _environment.CreateReferenceError(""); 56 | } 57 | return _bindingObject.Get(n); 58 | } 59 | 60 | public bool DeleteBinding(string n) 61 | { 62 | Contract.Assert(n != null); 63 | return _bindingObject.Delete(n, false); 64 | } 65 | 66 | public IDynamic ImplicitThisValue() 67 | { 68 | return _provideThis ? (IDynamic)_bindingObject : (IDynamic)_environment.Undefined; 69 | } 70 | 71 | public IDynamic Get(string name, bool strict) 72 | { 73 | return GetBindingValue(name, strict); 74 | } 75 | 76 | public void Set(string name, IDynamic value, bool strict) 77 | { 78 | SetMutableBinding(name, value, strict); 79 | } 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /Machete.Tests/Specification/Tests_07_Lexical_Conventions/Tests_07_02_WhiteSpace.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Globalization; 3 | using Machete.Parser; 4 | using Microsoft.FSharp.Core; 5 | using Xunit; 6 | 7 | namespace Machete.Tests.Specification.Tests_07_Lexical_Conventions 8 | { 9 | public class Tests_07_02_WhiteSpace : TestBase 10 | { 11 | [Fact(DisplayName = "07.02 White Space: TAB")] 12 | public void Test0702A() 13 | { 14 | var r = RunParser(InputElementParsers.parseWhiteSpace, "\u0009"); 15 | Assert.True(r.IsWhiteSpace, "The TAB character was not parsed as a White Space."); 16 | } 17 | 18 | [Fact(DisplayName = "07.02 White Space: VT")] 19 | public void Test0702B() 20 | { 21 | var r = RunParser(InputElementParsers.parseWhiteSpace, "\u000B"); 22 | Assert.True(r.IsWhiteSpace, "The VT character was not parsed as a White Space."); 23 | } 24 | 25 | [Fact(DisplayName = "07.02 White Space: FF")] 26 | public void Test0702C() 27 | { 28 | var r = RunParser(InputElementParsers.parseWhiteSpace, "\u000C"); 29 | Assert.True(r.IsWhiteSpace, "The FF character was not parsed as a White Space."); 30 | } 31 | 32 | [Fact(DisplayName = "07.02 White Space: SP")] 33 | public void Test0702D() 34 | { 35 | var r = RunParser(InputElementParsers.parseWhiteSpace, "\u0020"); 36 | Assert.True(r.IsWhiteSpace, "The SP character was not parsed as a White Space."); 37 | } 38 | 39 | [Fact(DisplayName = "07.02 White Space: NBSP")] 40 | public void Test0702E() 41 | { 42 | var r = RunParser(InputElementParsers.parseWhiteSpace, "\u00A0"); 43 | Assert.True(r.IsWhiteSpace, "The NBSP character was not parsed as a White Space."); 44 | } 45 | 46 | [Fact(DisplayName = "07.02 White Space: BOM")] 47 | public void Test0702F() 48 | { 49 | var r = RunParser(InputElementParsers.parseWhiteSpace, "\uFEFF"); 50 | Assert.True(r.IsWhiteSpace, "The BOM character was not parsed as a White Space."); 51 | } 52 | 53 | [Fact(DisplayName = "07.02 White Space: USP")] 54 | public void Test0702G() 55 | { 56 | for (char c = char.MinValue; c < char.MaxValue; c++) 57 | { 58 | switch (char.GetUnicodeCategory(c)) 59 | { 60 | case UnicodeCategory.SpaceSeparator: 61 | var r = RunParser(InputElementParsers.parseWhiteSpace, "\uFEFF"); 62 | Assert.True(r.IsWhiteSpace, "The USP character '" + c + "' was not parsed as a White Space."); 63 | break; 64 | } 65 | } 66 | } 67 | } 68 | } -------------------------------------------------------------------------------- /Machete.Tests/Lexical Conventions/NumericLiteral.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Xunit; 3 | using Machete.Core; 4 | 5 | namespace Machete.Tests 6 | { 7 | public sealed class NumericLiteral : TestBase 8 | { 9 | [Fact(DisplayName = "07.8.3 Numeric Literals: DecimalLiteral :: DecimalIntegerLiteral")] 10 | public void Test0783A() 11 | { 12 | Assert.Equal(999.0, (double)Engine.ExecuteScript("999")); 13 | } 14 | 15 | [Fact(DisplayName = "07.8.3 Numeric Literals: DecimalLiteral :: DecimalIntegerLiteral .")] 16 | public void Test0783B() 17 | { 18 | Assert.Equal(999.0, (double)Engine.ExecuteScript("999.")); 19 | } 20 | 21 | [Fact(DisplayName = "07.8.3 Numeric Literals: DecimalLiteral :: DecimalIntegerLiteral . DecimalDigits")] 22 | public void Test0783C() 23 | { 24 | Assert.Equal(999.222, (double)Engine.ExecuteScript("999.222")); 25 | } 26 | 27 | [Fact(DisplayName = "07.8.3 Numeric Literals: DecimalLiteral :: DecimalIntegerLiteral . ExponentPart")] 28 | public void Test0783D() 29 | { 30 | Assert.Equal(999.0e2, (double)Engine.ExecuteScript("999.e2")); 31 | } 32 | 33 | [Fact(DisplayName = "07.8.3 Numeric Literals: DecimalLiteral :: DecimalIntegerLiteral . DecimalDigits ExponentPart")] 34 | public void Test0783E() 35 | { 36 | Assert.Equal(999.222e2, (double)Engine.ExecuteScript("999.222e2")); 37 | } 38 | 39 | [Fact(DisplayName = "07.8.3 Numeric Literals: DecimalLiteral :: . DecimalDigits")] 40 | public void Test0783F() 41 | { 42 | Assert.Equal(.222, (double)Engine.ExecuteScript(".222")); 43 | } 44 | 45 | [Fact(DisplayName = "07.8.3 Numeric Literals: DecimalLiteral :: . DecimalDigits ExponentPart")] 46 | public void Test0783G() 47 | { 48 | Assert.Equal(.222e2, (double)Engine.ExecuteScript(".222e2")); 49 | } 50 | 51 | [Fact(DisplayName = "07.8.3 Numeric Literals: DecimalLiteral :: DecimalIntegerLiteral ExponentPart")] 52 | public void Test0783H() 53 | { 54 | Assert.Equal(999e2, (double)Engine.ExecuteScript("999e2")); 55 | } 56 | 57 | [Fact(DisplayName = "07.8.3 Numeric Literals: HexIntegerLiteral")] 58 | public void Test0783I() 59 | { 60 | Assert.Equal(0xFFF, (double)Engine.ExecuteScript("0xFFF")); 61 | Assert.Equal(0xFFF, (double)Engine.ExecuteScript("0XFFF")); 62 | Assert.Equal(0x12A, (double)Engine.ExecuteScript("0x12A")); 63 | } 64 | 65 | [Fact(DisplayName = "07.8.3 Numeric Literals: No Trailing IdentifierStart Or DecimalDigit")] 66 | public void Test0783J() 67 | { 68 | Assert.IsAssignableFrom(Engine.ExecuteScript("3in")); 69 | } 70 | } 71 | } -------------------------------------------------------------------------------- /Machete.Tests/Statements/VariableStatement.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Xunit; 3 | 4 | namespace Machete.Tests 5 | { 6 | public class VariableStatement : TestBase 7 | { 8 | [Fact(DisplayName = "12.2 Variable Statement -> Single declaration with no initializer.")] 9 | public void Test122A() 10 | { 11 | Assert.Equal("undefined", (string)Engine.ExecuteScript("var x;")); 12 | Assert.Equal("undefined", (string)Engine.ExecuteScript("typeof x")); 13 | Assert.True((bool)Engine.ExecuteScript("delete x")); 14 | } 15 | 16 | [Fact(DisplayName = "12.2 Variable Statement -> Single declaration with initializer.")] 17 | public void Test122B() 18 | { 19 | Assert.Equal("undefined", (string)Engine.ExecuteScript("var x = 1;")); 20 | Assert.Equal(1.0, (double)Engine.ExecuteScript("x")); 21 | Assert.True((bool)Engine.ExecuteScript("delete x")); 22 | } 23 | 24 | [Fact(DisplayName = "12.2 Variable Statement -> Many declarations with no initializers.")] 25 | public void Test122C() 26 | { 27 | Assert.Equal("undefined", (string)Engine.ExecuteScript("var x, y, z;")); 28 | Assert.Equal("undefined", (string)Engine.ExecuteScript("typeof x")); 29 | Assert.Equal("undefined", (string)Engine.ExecuteScript("typeof y")); 30 | Assert.Equal("undefined", (string)Engine.ExecuteScript("typeof z")); 31 | Assert.True((bool)Engine.ExecuteScript("delete x")); 32 | Assert.True((bool)Engine.ExecuteScript("delete y")); 33 | Assert.True((bool)Engine.ExecuteScript("delete z")); 34 | } 35 | 36 | [Fact(DisplayName = "12.2 Variable Statement -> Many declarations with initializers.")] 37 | public void Test122D() 38 | { 39 | Assert.Equal("undefined", (string)Engine.ExecuteScript("var x = 1, y = 2, z = 3;")); 40 | Assert.Equal(1.0, (double)Engine.ExecuteScript("x")); 41 | Assert.Equal(2.0, (double)Engine.ExecuteScript("y")); 42 | Assert.Equal(3.0, (double)Engine.ExecuteScript("z")); 43 | Assert.True((bool)Engine.ExecuteScript("delete x")); 44 | Assert.True((bool)Engine.ExecuteScript("delete y")); 45 | Assert.True((bool)Engine.ExecuteScript("delete z")); 46 | } 47 | 48 | [Fact(DisplayName = "12.2 Variable Statement -> Many declarations with some having initializers.")] 49 | public void Test122E() 50 | { 51 | Assert.Equal("undefined", (string)Engine.ExecuteScript("var x = 1, y, z = 3;")); 52 | Assert.Equal(1.0, (double)Engine.ExecuteScript("x")); 53 | Assert.Equal("undefined", (string)Engine.ExecuteScript("typeof y")); 54 | Assert.Equal(3.0, (double)Engine.ExecuteScript("z")); 55 | Assert.True((bool)Engine.ExecuteScript("delete x")); 56 | Assert.True((bool)Engine.ExecuteScript("delete y")); 57 | Assert.True((bool)Engine.ExecuteScript("delete z")); 58 | } 59 | } 60 | } -------------------------------------------------------------------------------- /Machete.Tests/Expressions/GeneratorExpression.cs: -------------------------------------------------------------------------------- 1 | using Machete.Core; 2 | using Xunit; 3 | 4 | namespace Machete.Tests.Expressions 5 | { 6 | public sealed class GeneratorExpression : TestBase 7 | { 8 | [Fact(DisplayName = "GeneratorExpression: YieldStatement")] 9 | public void TestA() 10 | { 11 | var r = Engine.ExecuteScriptToDynamic(@" 12 | (function() { 13 | var g = generator { 14 | yield 1; 15 | yield 1; 16 | yield 1; 17 | yield 1; 18 | yield 1; 19 | }; 20 | var r = 0; 21 | foreach (var n in g) { 22 | r += n; 23 | } 24 | return r; 25 | })(); 26 | "); 27 | Assert.IsAssignableFrom(r); 28 | Assert.Equal(5.0, ((INumber)r).BaseValue); 29 | } 30 | 31 | [Fact(DisplayName = "GeneratorExpression: YieldStatement With YieldBreakStatement")] 32 | public void TestB() 33 | { 34 | var r = Engine.ExecuteScriptToDynamic(@" 35 | (function() { 36 | var breakGen = true, 37 | g = generator { 38 | yield 1; 39 | yield 1; 40 | yield 1; 41 | yield 1; 42 | yield 1; 43 | if (breakGen) { 44 | yield break; 45 | } 46 | yield 1; 47 | }; 48 | var r = 0; 49 | foreach (var n in g) { 50 | r += n; 51 | } 52 | return r; 53 | })(); 54 | "); 55 | Assert.IsAssignableFrom(r); 56 | Assert.Equal(5.0, ((INumber)r).BaseValue); 57 | } 58 | 59 | [Fact(DisplayName = "GeneratorExpression: YieldStatement With YieldContinueStatement")] 60 | public void TestC() 61 | { 62 | var r = Engine.ExecuteScriptToDynamic(@" 63 | (function() { 64 | var g1 = generator { 65 | yield 1; 66 | yield 1; 67 | yield continue g2; 68 | }, 69 | g2 = generator { 70 | yield 1; 71 | yield 1; 72 | yield 1; 73 | }; 74 | var r = 0; 75 | foreach (var n in g) { 76 | r += n; 77 | } 78 | return r; 79 | })(); 80 | "); 81 | Assert.IsAssignableFrom(r); 82 | Assert.Equal(5.0, ((INumber)r).BaseValue); 83 | } 84 | } 85 | } -------------------------------------------------------------------------------- /Machete.Interactive/Interactive.fs: -------------------------------------------------------------------------------- 1 | namespace Machete.Interactive 2 | 3 | open System 4 | open System.Diagnostics 5 | open System.Text 6 | open System.Text.RegularExpressions 7 | open FParsec.CharParsers 8 | 9 | module Interactive = 10 | 11 | let private engine = new Machete.Engine() 12 | let private messageColor = ConsoleColor.Cyan 13 | let private defaultColor = ConsoleColor.Gray 14 | let private outputColor = ConsoleColor.DarkCyan 15 | let private statusColor = ConsoleColor.DarkGray 16 | let private errorColor = ConsoleColor.Red 17 | 18 | let write text color = 19 | lock 20 | engine 21 | (fun () -> 22 | let oldColor = Console.ForegroundColor 23 | Console.ForegroundColor <- color 24 | Console.Write (text:string) 25 | Console.ForegroundColor <- oldColor) 26 | 27 | 28 | let writeLine text color = 29 | lock 30 | engine 31 | (fun () -> 32 | let oldColor = Console.ForegroundColor 33 | Console.ForegroundColor <- color 34 | Console.WriteLine (text:string) 35 | Console.ForegroundColor <- oldColor) 36 | 37 | let rec private read () = 38 | let sb = StringBuilder() 39 | let run = ref true 40 | while !run do 41 | let line = Console.ReadLine () 42 | if line.EndsWith ";;" then 43 | run := false 44 | let line = line.Substring(0, line.Length - 2) 45 | sb.AppendLine line |> ignore 46 | else 47 | sb.AppendLine line |> ignore 48 | sb.ToString().Trim() 49 | 50 | let private isExn (o:obj) = 51 | match o with 52 | | :? Exception -> true 53 | | _ -> false 54 | 55 | let private loop () = 56 | while true do 57 | try 58 | let text = read () 59 | let sw = Stopwatch.StartNew() 60 | let r = engine.ExecuteScript text 61 | sw.Stop () 62 | let result, color = 63 | match r with 64 | | :? Exception as r -> r.Message, errorColor 65 | | _ -> r |> string, outputColor 66 | System.Threading.Thread.Sleep 100 67 | writeLine (result) color 68 | writeLine (sw.Elapsed.ToString() + "\n") statusColor 69 | with 70 | | e -> 71 | writeLine e.Message errorColor 72 | 73 | 74 | let initialize () = 75 | Console.OutputEncoding <- System.Text.Encoding.UTF8 76 | let message = "Machete Interactive " + AssemblyInfo.Version + "\n" 77 | engine.RegisterOutputHandler (fun s -> writeLine s outputColor) 78 | write ("Machete " + Machete.Core.AssemblyInfo.Version + "\n") messageColor 79 | write message messageColor 80 | write (Machete.Core.AssemblyInfo.Copyright + "\n\n") messageColor 81 | Console.Title <- message 82 | loop () -------------------------------------------------------------------------------- /Machete.Runtime/NativeObjects/BuiltinObjects/PBoolean.cs: -------------------------------------------------------------------------------- 1 | using Machete.Core; 2 | using Machete.Runtime.RuntimeTypes.LanguageTypes; 3 | 4 | namespace Machete.Runtime.NativeObjects.BuiltinObjects.PrototypeObjects 5 | { 6 | /// 7 | /// 15.6.4 Properties of the Boolean Prototype Object 8 | /// 9 | public sealed class PBoolean : LObject 10 | { 11 | private BFunction _toString; 12 | private BFunction _valueOf; 13 | 14 | public PBoolean(IEnvironment environment) 15 | : base(environment) 16 | { 17 | 18 | } 19 | 20 | /// 21 | /// 15.6.4.2 Boolean.prototype.toString ( ) 22 | /// 23 | public BFunction ToStringBuiltinFunction 24 | { 25 | get { return _toString; } 26 | } 27 | 28 | /// 29 | /// 15.6.4.3 Boolean.prototype.valueOf ( ) 30 | /// 31 | public BFunction ValueOfBuiltinFunction 32 | { 33 | get { return _valueOf; } 34 | } 35 | 36 | public sealed override void Initialize() 37 | { 38 | Class = "Boolean"; 39 | Extensible = true; 40 | Prototype = Environment.ObjectPrototype; 41 | 42 | _toString = new BFunction(Environment, ToString, ReadOnlyList.Empty); 43 | _valueOf = new BFunction(Environment, ValueOf, ReadOnlyList.Empty); 44 | 45 | new LObject.Builder(this) 46 | .SetAttributes(true, false, true) 47 | .AppendDataProperty("constructor", Environment.BooleanConstructor) 48 | .AppendDataProperty("toString", _toString) 49 | .AppendDataProperty("valueOf", _valueOf); 50 | } 51 | 52 | private static IDynamic ToString(IEnvironment environment, IArgs args) 53 | { 54 | var v = environment.Context.ThisBinding; 55 | switch (v.TypeCode) 56 | { 57 | case LanguageTypeCode.Boolean: 58 | return environment.CreateString(((IBoolean)v).BaseValue ? "true" : "false"); 59 | case LanguageTypeCode.Object: 60 | var o = (IObject)v; 61 | if (o.Class == "Boolean") 62 | { 63 | return environment.CreateString(((IBoolean)((IPrimitiveWrapper)o).PrimitiveValue).BaseValue ? "true" : "false"); 64 | } 65 | break; 66 | } 67 | throw environment.CreateTypeError(""); 68 | } 69 | 70 | private static IDynamic ValueOf(IEnvironment environment, IArgs args) 71 | { 72 | var v = environment.Context.ThisBinding; 73 | switch (v.TypeCode) 74 | { 75 | case LanguageTypeCode.Boolean: 76 | return v; 77 | case LanguageTypeCode.Object: 78 | var o = (IObject)v; 79 | if (o.Class == "Boolean") 80 | { 81 | return ((IPrimitiveWrapper)o).PrimitiveValue; 82 | } 83 | break; 84 | } 85 | throw environment.CreateTypeError(""); 86 | } 87 | } 88 | } -------------------------------------------------------------------------------- /Machete.Runtime/NativeObjects/BuiltinObjects/CArray.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Machete.Core; 3 | using Machete.Runtime.RuntimeTypes.LanguageTypes; 4 | 5 | namespace Machete.Runtime.NativeObjects.BuiltinObjects.ConstructorObjects 6 | { 7 | public sealed class CArray : BConstructor 8 | { 9 | public CArray(IEnvironment environment) 10 | : base(environment) 11 | { 12 | 13 | } 14 | 15 | public override void Initialize() 16 | { 17 | base.Initialize(); 18 | DefineOwnProperty("length", Environment.CreateDataDescriptor(Environment.CreateNumber(1.0), false, false, false), false); 19 | DefineOwnProperty("prototype", Environment.CreateDataDescriptor(Environment.ArrayPrototype, false, false, false), false); 20 | } 21 | 22 | protected override IDynamic Call(IEnvironment environment, IArgs args) 23 | { 24 | // 15.4.1.1 Array ( [ item1 [ , item2 [ , … ] ] ] ) 25 | 26 | return Construct(environment, args); 27 | } 28 | 29 | public override IObject Construct(IEnvironment environment, IArgs args) 30 | { 31 | var array = new NArray(Environment); 32 | array.Initialize(); 33 | if (args.Count != 1) 34 | { 35 | // 15.4.2.1 new Array ( [ item0 [ , item1 [ , … ] ] ] ) 36 | 37 | array.DefineOwnProperty("length", Environment.CreateDataDescriptor(Environment.CreateNumber(args.Count), true, false, false), false); 38 | for (int i = 0; i < args.Count; i++) 39 | { 40 | array.DefineOwnProperty(i.ToString(), Environment.CreateDataDescriptor(args[i], true, true, true), false); 41 | } 42 | } 43 | else 44 | { 45 | // 15.4.2.2 new Array (len) 46 | 47 | var arg0 = args[0]; 48 | if (arg0.TypeCode != LanguageTypeCode.Number) 49 | { 50 | array.DefineOwnProperty("length", Environment.CreateDataDescriptor(Environment.CreateNumber(1.0), true, false, false), false); 51 | array.DefineOwnProperty("0", Environment.CreateDataDescriptor(arg0, true, true, true), false); 52 | } 53 | else 54 | { 55 | var len = ((INumber)arg0).BaseValue; 56 | var uint32 = arg0.ConvertToUInt32().BaseValue; 57 | if (len != uint32) 58 | { 59 | throw Environment.CreateRangeError("The supplied length " + len + " does not fall into the unsigned 32-bit integer range."); 60 | } 61 | array.DefineOwnProperty("length", Environment.CreateDataDescriptor(arg0, true, false, false), false); 62 | } 63 | } 64 | 65 | return array; 66 | } 67 | 68 | [BuiltinFunction("isArray", "arg"), DataDescriptor(true, false, true)] 69 | internal static IDynamic IsArray(IEnvironment environment, IArgs args) 70 | { 71 | // 15.4.3.2 Array.isArray ( arg ) 72 | 73 | var arg = args[0] as IObject; 74 | return environment.CreateBoolean(arg != null && arg.Class == "Array"); 75 | } 76 | } 77 | } -------------------------------------------------------------------------------- /Machete.Runtime/RuntimeTypes/SpecificationTypes/SDeclarativeEnvironmentRecord.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using Machete.Runtime.RuntimeTypes.LanguageTypes; 6 | using Machete.Runtime.NativeObjects.BuiltinObjects; 7 | using Machete.Runtime.NativeObjects.BuiltinObjects.ConstructorObjects; 8 | using Machete.Core; 9 | 10 | namespace Machete.Runtime.RuntimeTypes.SpecificationTypes 11 | { 12 | public sealed class SDeclarativeEnvironmentRecord : IDeclarativeEnvironmentRecord 13 | { 14 | private readonly IEnvironment _environment; 15 | private readonly Dictionary _bindings = new Dictionary(); 16 | 17 | 18 | public SDeclarativeEnvironmentRecord(IEnvironment environment) 19 | { 20 | _environment = environment; 21 | } 22 | 23 | 24 | public bool HasBinding(string n) 25 | { 26 | return _bindings.ContainsKey(n); 27 | } 28 | 29 | public void CreateMutableBinding(string n, bool d) 30 | { 31 | _bindings.Add(n, new Binding(_environment.Undefined, d ? BFlags.Deletable : BFlags.None)); 32 | } 33 | 34 | public void SetMutableBinding(string n, IDynamic v, bool s) 35 | { 36 | var binding = _bindings[n]; 37 | if ((binding.Flags & BFlags.Immutable) == BFlags.Immutable) 38 | { 39 | throw _environment.CreateUriError(""); 40 | } 41 | binding.Value = v; 42 | } 43 | 44 | public IDynamic GetBindingValue(string n, bool s) 45 | { 46 | var binding = _bindings[n]; 47 | if ((binding.Flags & BFlags.Uninitialized) == BFlags.Uninitialized) 48 | { 49 | if (!s) return _environment.Undefined; 50 | throw _environment.CreateReferenceError(""); 51 | } 52 | return binding.Value; 53 | } 54 | 55 | public bool DeleteBinding(string n) 56 | { 57 | var binding = default(Binding); 58 | if (!_bindings.TryGetValue(n, out binding)) 59 | { 60 | return true; 61 | } 62 | if ((binding.Flags & BFlags.Deletable) != BFlags.Deletable) 63 | { 64 | return false; 65 | } 66 | _bindings.Remove(n); 67 | return true; 68 | } 69 | 70 | public IDynamic ImplicitThisValue() 71 | { 72 | return _environment.Undefined; 73 | } 74 | 75 | public IDynamic Get(string name, bool strict) 76 | { 77 | return GetBindingValue(name, strict); 78 | } 79 | 80 | public void Set(string name, IDynamic value, bool strict) 81 | { 82 | SetMutableBinding(name, value, strict); 83 | } 84 | 85 | public void CreateImmutableBinding(string n) 86 | { 87 | _bindings.Add(n, new Binding(_environment.Undefined, BFlags.Immutable | BFlags.Uninitialized)); 88 | } 89 | 90 | public void InitializeImmutableBinding(string n, IDynamic v) 91 | { 92 | _bindings[n].Value = v; 93 | } 94 | 95 | 96 | [Flags] 97 | private enum BFlags 98 | { 99 | None, 100 | Deletable, 101 | Immutable, 102 | Initialized, 103 | Uninitialized, 104 | } 105 | 106 | private sealed class Binding 107 | { 108 | public IDynamic Value; 109 | public BFlags Flags; 110 | 111 | public Binding(IDynamic value, BFlags flags) 112 | { 113 | Value = value; 114 | Flags = flags; 115 | } 116 | } 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /Machete.Tests/Expressions/AssignmentOperators.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Xunit; 3 | 4 | namespace Machete.Tests 5 | { 6 | public class AssignmentOperators : TestBase 7 | { 8 | [Fact(DisplayName = "11.13 Assignment Operators -> Simple")] 9 | public void Test1113A() 10 | { 11 | Assert.Equal(2.0, (double)Engine.ExecuteScript("var x = 1; x = 2;")); 12 | Assert.True((bool)Engine.ExecuteScript("delete x;")); 13 | } 14 | 15 | [Fact(DisplayName = "11.13 Assignment Operators -> Compound Multiplication")] 16 | public void Test1113B() 17 | { 18 | Assert.Equal(4.0, (double)Engine.ExecuteScript("var x = 2; x *= 2;")); 19 | Assert.True((bool)Engine.ExecuteScript("delete x;")); 20 | } 21 | 22 | [Fact(DisplayName = "11.13 Assignment Operators -> Compound Division")] 23 | public void Test1113C() 24 | { 25 | Assert.Equal(0.5, (double)Engine.ExecuteScript("var x = 1; x /= 2;")); 26 | Assert.True((bool)Engine.ExecuteScript("delete x;")); 27 | } 28 | 29 | [Fact(DisplayName = "11.13 Assignment Operators -> Compound Modulus")] 30 | public void Test1113D() 31 | { 32 | Assert.Equal(0.0, (double)Engine.ExecuteScript("var x = 10; x %= 2;")); 33 | Assert.True((bool)Engine.ExecuteScript("delete x;")); 34 | } 35 | 36 | [Fact(DisplayName = "11.13 Assignment Operators -> Compound Addition")] 37 | public void Test1113E() 38 | { 39 | Assert.Equal(12.0, (double)Engine.ExecuteScript("var x = 10; x += 2;")); 40 | Assert.True((bool)Engine.ExecuteScript("delete x;")); 41 | } 42 | 43 | [Fact(DisplayName = "11.13 Assignment Operators -> Compound Subtraction")] 44 | public void Test1113F() 45 | { 46 | Assert.Equal(8.0, (double)Engine.ExecuteScript("var x = 10; x -= 2;")); 47 | Assert.True((bool)Engine.ExecuteScript("delete x;")); 48 | } 49 | 50 | [Fact(DisplayName = "11.13 Assignment Operators -> Compound Left Shift")] 51 | public void Test1113G() 52 | { 53 | Assert.Equal(16.0, (double)Engine.ExecuteScript("var x = 4; x <<= 2;")); 54 | Assert.True((bool)Engine.ExecuteScript("delete x;")); 55 | } 56 | 57 | [Fact(DisplayName = "11.13 Assignment Operators -> Compound Signed Right Shift")] 58 | public void Test1113H() 59 | { 60 | Assert.Equal(-536870912.0, (double)Engine.ExecuteScript("var x = 2147483648; x >>= 2;")); 61 | Assert.True((bool)Engine.ExecuteScript("delete x;")); 62 | } 63 | 64 | [Fact(DisplayName = "11.13 Assignment Operators -> Compound Unsigned Right Shift")] 65 | public void Test1113I() 66 | { 67 | Assert.Equal(536870912.0, (double)Engine.ExecuteScript("var x = 2147483648; x >>>= 2;")); 68 | Assert.True((bool)Engine.ExecuteScript("delete x;")); 69 | } 70 | 71 | [Fact(DisplayName = "11.13 Assignment Operators -> Compound Bitwise AND")] 72 | public void Test1113J() 73 | { 74 | Assert.Equal(2.0, (double)Engine.ExecuteScript("var x = 3; x &= 2;")); 75 | Assert.True((bool)Engine.ExecuteScript("delete x;")); 76 | } 77 | 78 | [Fact(DisplayName = "11.13 Assignment Operators -> Compound Bitwise XOR")] 79 | public void Test1113K() 80 | { 81 | Assert.Equal(1 ^ 2, (double)Engine.ExecuteScript("var x = 1; x ^= 2;")); 82 | Assert.True((bool)Engine.ExecuteScript("delete x;")); 83 | } 84 | 85 | [Fact(DisplayName = "11.13 Assignment Operators -> Compound Bitwise OR")] 86 | public void Test1113L() 87 | { 88 | Assert.Equal(3.0, (double)Engine.ExecuteScript("var x = 1; x |= 2;")); 89 | Assert.True((bool)Engine.ExecuteScript("delete x;")); 90 | } 91 | } 92 | } -------------------------------------------------------------------------------- /Machete.Tests/Standard Built-in ECMAScript Objects/FunctionObjects.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using Xunit; 3 | 4 | namespace Machete.Tests 5 | { 6 | public class FunctionObjects : TestBase 7 | { 8 | [Fact(DisplayName = "15.3.1.1 Function (p1, p2, … , pn, body)")] 9 | public void Test15311() 10 | { 11 | var script = @" 12 | (function() { 13 | var add = Function('x', 'y', 'return x + y'); 14 | return add(1, 2); 15 | })(); 16 | "; 17 | ExpectDouble(script, 3.0); 18 | } 19 | 20 | [Fact(DisplayName = "15.3.2.1 new Function (p1, p2, … , pn, body)")] 21 | public void Test15321() 22 | { 23 | var script = @" 24 | (function() { 25 | var add = new Function('x', 'y', 'return x + y'); 26 | return add(1, 2); 27 | })(); 28 | "; 29 | ExpectDouble(script, 3.0); 30 | } 31 | 32 | [Fact(DisplayName = "15.3.3.1 Function.prototype")] 33 | public void Test15331() 34 | { 35 | Assert.True((bool)Engine.ExecuteScript("Function.prototype.isPrototypeOf(Object)")); 36 | } 37 | 38 | [Fact(DisplayName = "15.3.3.2 Function.length")] 39 | public void Test15332() 40 | { 41 | Assert.True((bool)Engine.ExecuteScript("Function.length === 1")); 42 | } 43 | 44 | [Fact(DisplayName = "15.3.4.1 Function.prototype.constructor")] 45 | public void Test15341() 46 | { 47 | Assert.True((bool)Engine.ExecuteScript("Function.prototype.constructor === Function")); 48 | } 49 | 50 | [Fact(DisplayName = "15.3.4.2 Function.prototype.toString ( )")] 51 | public void Test15342() 52 | { 53 | Assert.True((bool)Engine.ExecuteScript("parseInt.toString() === '[object, Function]'")); 54 | } 55 | 56 | [Fact(DisplayName = "15.3.4.3 Function.prototype.apply (thisArg, argArray)")] 57 | public void Test15343() 58 | { 59 | var script = @" 60 | (function() { 61 | var ags = [1, 2]; 62 | var obj = { 63 | value: 100 64 | }; 65 | function add(x, y) { 66 | return this.value + x + y; 67 | } 68 | return add.apply(obj, ags); 69 | })(); 70 | "; 71 | ExpectDouble(script, 103.0); 72 | } 73 | 74 | [Fact(DisplayName = "15.3.4.4 Function.prototype.call (thisArg [ , arg1 [ , arg2, … ] ] )")] 75 | public void Test15344() 76 | { 77 | var script = @" 78 | (function() { 79 | var obj = { 80 | value: 999 81 | }; 82 | function add(x, y) { 83 | return x + y; 84 | } 85 | function callAdd(y) { 86 | return add(this.value, y); 87 | } 88 | return callAdd.call(obj, 1); 89 | })(); 90 | "; 91 | ExpectDouble(script, 1000.0); 92 | } 93 | 94 | [Fact(DisplayName = "15.3.4.5 Function.prototype.bind (thisArg [, arg1 [, arg2, …]])")] 95 | public void Test15345() 96 | { 97 | var script = @" 98 | (function() { 99 | function add(x, y) { 100 | return x + y; 101 | } 102 | var add1 = add.bind(this, 1); 103 | return add1(2); 104 | })(); 105 | "; 106 | ExpectDouble(script, 3.0); 107 | } 108 | } 109 | } -------------------------------------------------------------------------------- /Machete/Engine.fs: -------------------------------------------------------------------------------- 1 | namespace Machete 2 | 3 | open System 4 | open System.Collections.Generic 5 | open Machete.Core 6 | open Machete.Runtime 7 | open Machete.Compiler 8 | 9 | type internal Message = 10 | | ExecuteScript of string * AsyncReplyChannel 11 | | ExecuteScriptToDynamic of string * AsyncReplyChannel 12 | | RegisterOutputHandler of Action 13 | 14 | type Engine () = 15 | 16 | let environment = new Environment() 17 | let compiler = new CompilerService(environment) 18 | let handlers = Dictionary, MailboxProcessor>>() 19 | 20 | 21 | let checkOutput (inbox:MailboxProcessor>) = async { 22 | let! handler = inbox.Receive () 23 | while true do 24 | try 25 | let str = environment.Output.Take() 26 | handler.Invoke str 27 | with | e -> () 28 | } 29 | 30 | let proccessMessages (inbox:MailboxProcessor) = async { 31 | do! Async.SwitchToNewThread () 32 | while true do 33 | try 34 | let! msg = inbox.Receive () 35 | match msg with 36 | | RegisterOutputHandler (handler) -> 37 | let agent = MailboxProcessor.Start checkOutput 38 | agent.Post handler 39 | handlers.Add (handler, agent) 40 | | ExecuteScript (script, channel) -> 41 | try 42 | let executableCode = compiler.CompileGlobalCode script 43 | let result = environment.Execute executableCode 44 | let result = 45 | match result.Value with 46 | | :? IBoolean as r -> r.BaseValue :> obj 47 | | :? INumber as r -> r.BaseValue :> obj 48 | | :? IString as r -> r.BaseValue :> obj 49 | | _ -> result.ToString() :> obj 50 | channel.Reply result 51 | with | e -> 52 | channel.Reply e 53 | | ExecuteScriptToDynamic (script, channel) -> 54 | try 55 | let executableCode = compiler.CompileGlobalCode script 56 | let result = environment.Execute executableCode 57 | channel.Reply result 58 | with | e -> 59 | channel.Reply (environment.CreateString e.Message) 60 | with | e -> () 61 | } 62 | 63 | let agent = lazy(MailboxProcessor.Start proccessMessages) 64 | 65 | let buildExecuteScriptMessage script channel = 66 | ExecuteScript (script, channel) 67 | 68 | member this.ExecuteScriptToDynamic (script:string) = 69 | agent.Value.PostAndReply (fun channel -> ExecuteScriptToDynamic (script, channel)) 70 | 71 | member this.ExecuteScript (script:string) = 72 | agent.Value.PostAndReply (buildExecuteScriptMessage script) 73 | 74 | member this.ExecuteScript (script:string, timeout:int) = 75 | agent.Value.PostAndReply (buildExecuteScriptMessage script, timeout) 76 | 77 | member this.ExecuteScriptAsync (script:string) = 78 | agent.Value.PostAndAsyncReply (buildExecuteScriptMessage script) 79 | 80 | member this.ExecuteScriptAsync (script:string, timeout:int) = 81 | agent.Value.PostAndAsyncReply (buildExecuteScriptMessage script, timeout) 82 | 83 | member this.ExecuteScriptAsTask (script:string) = 84 | agent.Value.PostAndAsyncReply (buildExecuteScriptMessage script) |> Async.StartAsTask 85 | 86 | member this.ExecuteScriptAsTask (script:string, timeout:int) = 87 | agent.Value.PostAndAsyncReply (buildExecuteScriptMessage script, timeout) |> Async.StartAsTask 88 | 89 | member this.RegisterOutputHandler (handler:Action) = 90 | agent.Value.Post (RegisterOutputHandler handler) -------------------------------------------------------------------------------- /Machete.Runtime/NativeObjects/BuiltinObjects/CRegExp.cs: -------------------------------------------------------------------------------- 1 | using Machete.Core; 2 | using Machete.Runtime.RuntimeTypes.LanguageTypes; 3 | 4 | namespace Machete.Runtime.NativeObjects.BuiltinObjects.ConstructorObjects 5 | { 6 | public sealed class CRegExp : BConstructor 7 | { 8 | public CRegExp(IEnvironment environment) 9 | : base(environment) 10 | { 11 | 12 | } 13 | 14 | public sealed override void Initialize() 15 | { 16 | base.Initialize(); 17 | DefineOwnProperty("length", Environment.CreateDataDescriptor(Environment.CreateNumber(2.0), false, false, false), false); 18 | DefineOwnProperty("prototype", Environment.CreateDataDescriptor(Environment.RegExpPrototype, false, false, false), false); 19 | } 20 | 21 | protected sealed override IDynamic Call(IEnvironment environment, IArgs args) 22 | { 23 | var patternObject = args[0] as IObject; 24 | if (patternObject != null && patternObject.Class == "RegExp") 25 | { 26 | return patternObject; 27 | } 28 | return Construct(environment, args); 29 | } 30 | 31 | public sealed override IObject Construct(IEnvironment environment, IArgs args) 32 | { 33 | var patternArg = args[0]; 34 | var flagsArg = args[1]; 35 | var pattern = ""; 36 | var flags = ""; 37 | bool global, ignoreCase, multiline; 38 | 39 | var patternObject = patternArg as IObject; 40 | if (patternObject != null && patternObject.Class == "RegExp") 41 | { 42 | if (flagsArg.TypeCode != LanguageTypeCode.Undefined) 43 | { 44 | throw environment.CreateTypeError(""); 45 | } 46 | global = ((IBoolean)patternObject.Get("global")).BaseValue; 47 | ignoreCase = ((IBoolean)patternObject.Get("ignoreCase")).BaseValue; 48 | multiline = ((IBoolean)patternObject.Get("multiline")).BaseValue; 49 | pattern = ((IString)patternObject.Get("source")).BaseValue; 50 | if (global) flags += "g"; 51 | if (ignoreCase) flags += "i"; 52 | if (multiline) flags += "m"; 53 | } 54 | else 55 | { 56 | if (patternArg.TypeCode != LanguageTypeCode.Undefined) 57 | { 58 | pattern = patternArg.ConvertToString().BaseValue; 59 | } 60 | if (flagsArg.TypeCode != LanguageTypeCode.Undefined) 61 | { 62 | flags = flagsArg.ConvertToString().BaseValue; 63 | } 64 | global = flags.Contains("g"); 65 | ignoreCase = flags.Contains("i"); 66 | multiline = flags.Contains("m"); 67 | } 68 | 69 | var regExpObj = new NRegExp(environment); 70 | regExpObj.Class = "RegExp"; 71 | regExpObj.Extensible = true; 72 | regExpObj.Prototype = environment.RegExpPrototype; 73 | regExpObj.Body = pattern; 74 | regExpObj.Flags = flags; 75 | regExpObj.RegExpMatcher = Machete.Compiler.RegExpParser.Parse(Environment, pattern, flags); 76 | regExpObj.DefineOwnProperty("source", environment.CreateDataDescriptor(environment.CreateString(pattern), false, false, false), false); 77 | regExpObj.DefineOwnProperty("global", environment.CreateDataDescriptor(environment.CreateBoolean(global), false, false, false), false); 78 | regExpObj.DefineOwnProperty("ignoreCase", environment.CreateDataDescriptor(environment.CreateBoolean(ignoreCase), false, false, false), false); 79 | regExpObj.DefineOwnProperty("multiline", environment.CreateDataDescriptor(environment.CreateBoolean(multiline), false, false, false), false); 80 | regExpObj.DefineOwnProperty("lastIndex", environment.CreateDataDescriptor(environment.CreateNumber(0.0), true, false, false), false); 81 | return regExpObj; 82 | } 83 | } 84 | } -------------------------------------------------------------------------------- /Machete.Runtime/HostObjects/Iterables/HIterable.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using Machete.Core; 6 | using Machete.Runtime.NativeObjects.BuiltinObjects; 7 | using Machete.Runtime.RuntimeTypes.LanguageTypes; 8 | 9 | namespace Machete.Runtime.HostObjects.Iterables 10 | { 11 | public sealed class HIterable : LObject 12 | { 13 | public BFunction ToArrayBuiltinFunction { get; private set; } 14 | public BFunction IterateBuiltinFunction { get; private set; } 15 | public BFunction FilterStringBuiltinFunction { get; private set; } 16 | public BFunction MapStringBuiltinFunction { get; private set; } 17 | 18 | public HIterable(IEnvironment environment) 19 | : base(environment) 20 | { 21 | Class = "Iterable"; 22 | Prototype = environment.ObjectPrototype; 23 | Extensible = true; 24 | 25 | ToArrayBuiltinFunction = new BFunction(environment, ToArray, new ReadOnlyList("iterable")); 26 | IterateBuiltinFunction = new BFunction(environment, Iterate, new ReadOnlyList("callback", "iterable")); 27 | FilterStringBuiltinFunction = new BFunction(environment, Filter, new ReadOnlyList("predicate", "iterable")); 28 | MapStringBuiltinFunction = new BFunction(environment, Map, new ReadOnlyList("mapping", "iterable")); 29 | 30 | new LObject.Builder(this) 31 | .SetAttributes(false, false, false) 32 | .AppendDataProperty("toArray", ToArrayBuiltinFunction) 33 | .AppendDataProperty("iterate", IterateBuiltinFunction) 34 | .AppendDataProperty("filter", FilterStringBuiltinFunction) 35 | .AppendDataProperty("map", MapStringBuiltinFunction); 36 | } 37 | 38 | internal static IDynamic ToArray(IEnvironment environment, IArgs args) 39 | { 40 | var array = ((IConstructable)environment.ArrayConstructor).Construct(environment, environment.EmptyArgs); 41 | var builder = environment.CreateObjectBuilder(array).SetAttributes(true, true, true); 42 | var iterator = new Iterator(environment, args[0]); 43 | 44 | uint index = 0; 45 | while (iterator.Next()) 46 | { 47 | builder.AppendDataProperty(index.ToString(), iterator.Current); 48 | index++; 49 | } 50 | 51 | array.Put("length", environment.CreateNumber(index), true); 52 | 53 | return array; 54 | } 55 | 56 | internal static IDynamic Iterate(IEnvironment environment, IArgs args) 57 | { 58 | var iterator = new Iterator(environment, args[1]); 59 | var callback = args[0] as ICallable; 60 | if (callback == null) 61 | throw environment.CreateTypeError("The argument 'callback' must be a callable function."); 62 | while (iterator.Next()) 63 | { 64 | var callArgs = environment.CreateArgs(new[] { iterator.Current }); 65 | callback.Call(environment, environment.Undefined, callArgs); 66 | } 67 | return environment.Undefined; 68 | } 69 | 70 | internal static IDynamic Filter(IEnvironment environment, IArgs args) 71 | { 72 | if (args.Count < 2) 73 | throw environment.CreateTypeError("The arguments 'iterable' and 'predicate' are required."); 74 | var iterable = args[1].ConvertToObject(); 75 | var predicate = args[0].ConvertToObject() as ICallable; 76 | if (predicate == null) 77 | throw environment.CreateTypeError("The argument 'predicate' must be a callable function."); 78 | return new HFilterIterable(environment, iterable, predicate); 79 | } 80 | 81 | internal static IDynamic Map(IEnvironment environment, IArgs args) 82 | { 83 | if (args.Count < 2) 84 | throw environment.CreateTypeError("The arguments 'iterable' and 'mapping' are required."); 85 | var iterable = args[1].ConvertToObject(); 86 | var mapping = args[0].ConvertToObject() as ICallable; 87 | if (mapping == null) 88 | throw environment.CreateTypeError("The argument 'mapping' must be a callable function."); 89 | return new HMapIterable(environment, iterable, mapping); 90 | } 91 | } 92 | } -------------------------------------------------------------------------------- /Machete.Tests/Statements/ForeachStatement.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using Xunit; 6 | using Machete.Core; 7 | 8 | namespace Machete.Tests.Statements 9 | { 10 | public sealed class ForeachStatement : TestBase 11 | { 12 | [Fact(DisplayName = "Foreach - Iterate Over Array")] 13 | public void IterateOverArray() 14 | { 15 | var script = @" 16 | (function() { 17 | var r = 0; 18 | foreach (var n in [10, 10, 10, 10, 10]) { 19 | r += n; 20 | } 21 | return r; 22 | })(); 23 | "; 24 | var r = Engine.ExecuteScriptToDynamic(script); 25 | Assert.IsAssignableFrom(r); 26 | Assert.Equal(50.0, ((INumber)r).BaseValue); 27 | } 28 | 29 | [Fact(DisplayName = "Foreach - Iterate Over String")] 30 | public void IterateOverString() 31 | { 32 | var script = @" 33 | (function() { 34 | var r = ''; 35 | foreach (var c in 'ABC') { 36 | r += c; 37 | } 38 | return r; 39 | })(); 40 | "; 41 | var r = Engine.ExecuteScriptToDynamic(script); 42 | Assert.IsAssignableFrom(r); 43 | Assert.Equal("ABC", ((IString)r).BaseValue); 44 | } 45 | 46 | [Fact(DisplayName = "Foreach - Iterate Over Generator")] 47 | public void IterateOverGenerator() 48 | { 49 | var script = @" 50 | (function() { 51 | var g = generator { 52 | yield 10; 53 | yield 10; 54 | yield 10; 55 | yield 10; 56 | yield 10; 57 | }; 58 | var r = 0; 59 | foreach (var n in g) { 60 | r += n; 61 | } 62 | return r; 63 | })(); 64 | "; 65 | var r = Engine.ExecuteScriptToDynamic(script); 66 | Assert.IsAssignableFrom(r); 67 | Assert.Equal(50.0, ((INumber)r).BaseValue); 68 | } 69 | 70 | [Fact(DisplayName = "Foreach - Iterate Over Custom Iterator")] 71 | public void IterateOverCustomIterator() 72 | { 73 | var script = @" 74 | (function() { 75 | function Iterator() { 76 | var i = 0, self = this; 77 | 78 | this.current = null; 79 | 80 | this.next = function() { 81 | if (i < 5) { 82 | self.current = ++i; 83 | return true; 84 | } 85 | return false; 86 | }; 87 | 88 | this.createIterator = function() { 89 | return this; 90 | }; 91 | } 92 | var r = 0, x = new Iterator(); 93 | foreach (var n in x) { 94 | r += n; 95 | } 96 | return r; 97 | })(); 98 | "; 99 | var r = Engine.ExecuteScriptToDynamic(script); 100 | Assert.IsAssignableFrom(r); 101 | Assert.Equal(15.0, ((INumber)r).BaseValue); 102 | } 103 | 104 | [Fact(DisplayName = "Foreach - IfStatement")] 105 | public void LoopWithIfStatement() 106 | { 107 | var script = @" 108 | (function() { 109 | var r = 0; 110 | foreach (var n in [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]) 111 | if (n % 2 === 0) 112 | r += n; 113 | return r; 114 | })(); 115 | "; 116 | var r = Engine.ExecuteScriptToDynamic(script); 117 | Assert.IsAssignableFrom(r); 118 | Assert.Equal(30.0, ((INumber)r).BaseValue); 119 | } 120 | } 121 | } --------------------------------------------------------------------------------