public void EvalAnd_ReturnTrue_WhenTailIsEmptyList() { var expr = BuiltIn.ListOf(ClSymbol.And); var ctx = expr.Reduce(_ctx); Assert.That(ctx.Value, Is.EqualTo(ClBool.True)); }
public override IContext Reduce(IContext ctx) { var funcName = BuiltIn.Head(Cdr); var lambda = new ClCell(ClSymbol.Lambda, BuiltIn.Tail(Cdr)); return(BuiltIn.ListOf(ClSymbol.Define, funcName, lambda).Reduce(ctx)); }
public void EvalCond_ReturnFalse_WhenClausesAreMissed() { var expr = BuiltIn.ListOf(ClSymbol.Cond); var ctx = expr.Reduce(_ctx); Assert.That(ctx.Value, Is.EqualTo(ClBool.False)); }
public void EvalDefinition_ThrowException_WhenRighSideVariableDoesNotExist() { var expr = BuiltIn.ListOf(ClSymbol.Define, Var.Foo, Var.Bar); Assert.That(() => expr.Reduce(_ctx), Throws.Exception.TypeOf <UnboundVariableError>().With.Message.EqualTo("Unbound variable bar")); }
public void EvalDefinition_CreateNewBinding() { var expr = BuiltIn.ListOf(ClSymbol.Define, Var.Foo, ClBool.True); var ctx = expr.Reduce(_ctx); Assert.That(ctx.Env.Lookup(Var.Foo), Is.EqualTo(ClBool.True)); }
public void EvalBegin_ReturnNil_WhenTailIsEmptyList() { var expr = BuiltIn.ListOf(ClSymbol.Begin); var ctx = expr.Reduce(_ctx); Assert.That(ctx.Value, Is.EqualTo(ClCell.Nil)); }
public void EvalAnd_ReturnLastItem_WhenEachItemIsTrue() { var expr = BuiltIn.ListOf(ClSymbol.And, ClBool.True, Value.Foo); var ctx = expr.Reduce(_ctx); Assert.That(ctx.Value, Is.EqualTo(Value.Foo)); }
public void Eval_DoesNotCreateNewScope(Func <ClCell, ClCell> expr) { var define = BuiltIn.ListOf(ClSymbol.Define, Var.Foo, Value.Foo); var ctx = expr.Invoke(define).Reduce(_ctx); Assert.That(ctx.Env.Lookup(Var.Foo), Is.EqualTo(Value.Foo)); }
public void EvalIf_ReturnNil_WhenConditionIsFalseAndElseBranchIsMissed() { var expr = BuiltIn.ListOf(ClSymbol.If, ClBool.False, Value.One); var ctx = expr.Reduce(_ctx); Assert.That(ctx.Value, Is.EqualTo(ClCell.Nil)); }
public void EvalLet_LikeConstantFunction() { var expr = BuiltIn.ListOf(ClSymbol.Let, ClCell.Nil, Value.One); var ctx = expr.Reduce(_ctx); Assert.That(ctx.Value, Is.EqualTo(Value.One)); }
public void EvalAssignment_ThrowException_WhenEnvironmentDoesNotContainBinding() { var expr = BuiltIn.ListOf(ClSymbol.Set, Var.Foo, Value.Foo); Assert.That(() => expr.Reduce(_ctx), Throws.Exception.TypeOf <UnboundVariableError>().With.Message.EqualTo("Unbound variable foo")); }
public void EvalIf_EvalThenBranch_WhenConditionIsTrue(ClObj predicate) { var expr = BuiltIn.ListOf(ClSymbol.If, predicate, Value.One, ClBool.False); var ctx = expr.Reduce(_ctx); Assert.That(ctx.Value, Is.EqualTo(Value.One)); }
public void EvalOr_ReturnFalse_WhenTailIsEmptyList() { var expr = BuiltIn.ListOf(ClSymbol.Or); var ctx = expr.Reduce(_ctx); Assert.That(ctx.Value, Is.EqualTo(ClBool.False)); }
public void EvalBegin_ReturnLastEvaluatedValue() { var expr = BuiltIn.ListOf(ClSymbol.Begin, ClBool.False, ClBool.True, Value.One); var ctx = expr.Reduce(_ctx); Assert.That(ctx.Value, Is.EqualTo(Value.One)); }
public void EvalDefinition_ReturnNil_WhenOperationIsSuccessful() { var expr = BuiltIn.ListOf(ClSymbol.Define, Var.Foo, ClBool.False); var ctx = expr.Reduce(_ctx); Assert.That(ctx.Value, Is.EqualTo(ClCell.Nil)); }
static IEnumerable <ClObj> InvalidParameterTestCases() { yield return(Value.One); yield return(Value.Foo); yield return(BuiltIn.ListOf(ClSymbol.If, ClBool.True, Var.Foo, Var.Bar)); }
static IEnumerable <Func <ClCell, ClCell> > DoesNotCreateNewScopeTestCases() { yield return(new Func <ClCell, ClCell>(x => BuiltIn.ListOf(ClSymbol.If, x, ClBool.True, ClBool.False))); yield return(new Func <ClCell, ClCell>(x => BuiltIn.ListOf(ClSymbol.And, x, ClBool.False))); yield return(new Func <ClCell, ClCell>(x => BuiltIn.ListOf(ClSymbol.Or, x, ClBool.True))); }
public void Env_InjectPredifinedEntities() { var env = new Env(BuiltIn.Env); var nativeFn = env.Lookup(new ClSymbol("head")).Cast <NativeFn>(); var args = BuiltIn.ListOf(ClBool.True, ClBool.False); Assert.That(nativeFn.Apply(args), Is.EqualTo(ClBool.True)); }
public void EvalLambda_ThrowException_WhenLambdaSpecialFormHasInvalidBody() { var expr = BuiltIn.ListOf(ClSymbol.Lambda, ClCell.Nil, ClBool.True, ClBool.False); var errorMessage = "Invalid function body format"; Assert.That(() => expr.Reduce(_ctx), Throws.Exception.TypeOf <SyntaxError>().With.Message.EqualTo(errorMessage)); }
public void Eval_IdentifiersAndKeywordsCoexistIndependently() { _env.Bind(ClSymbol.And, Value.One); var expr = BuiltIn.ListOf(ClSymbol.And, ClBool.True, Value.Foo); Assert.That(ClSymbol.And.Reduce(_ctx).Value, Is.EqualTo(Value.One)); Assert.That(expr.Reduce(_ctx).Value, Is.EqualTo(Value.Foo)); }
public override IContext Reduce(IContext ctx) { var identifier = BuiltIn.First(Cdr).Cast <ClSymbol>(); var newCtx = BuiltIn.Second(Cdr).Reduce(ctx); newCtx.Env.Assign(identifier, newCtx.Value); return(new Context(newCtx.Env)); }
public void EvalLambda_ThrowExceptionWhenParametersIsNotList() { var expr = BuiltIn.ListOf(ClSymbol.Lambda, Var.Foo, Var.Foo); var errorMessage = "Invalid function parameters format"; Assert.That(() => expr.Reduce(_ctx), Throws.Exception.TypeOf <SyntaxError>().With.Message.EqualTo(errorMessage)); }
public override IContext Reduce(IContext ctx) { var identifier = BuiltIn.First(Cdr).Cast <ClSymbol>(); var(value, env) = BuiltIn.Second(Cdr).Reduce(ctx); env.Bind(identifier, value); return(new Context(env)); }
public void SnippetsTest(string snippet, string expected) { using var source = new Source(snippet); var reader = new Reader(); var(actual, _) = BuiltIn.Eval(reader.Read(source)); Assert.That(actual.ToString(), Is.EqualTo(expected)); }
public void EvalApplication_ThrowException_WhenBodyContainsUnboundVariable() { var procedure = BuiltIn.ListOf(ClSymbol.Lambda, ClCell.Nil, Var.Bar); var expr = BuiltIn.ListOf(procedure); Assert.That(() => expr.Reduce(_ctx), Throws.Exception.TypeOf <UnboundVariableError>().With.Message.EqualTo("Unbound variable bar")); }
public void Eval_ReturnUnreducedExpression_WhenItIsQuoted() { var cell = new ClCell(new ClInt(1), new ClInt(2)); var expr = BuiltIn.Quote(cell); var ctx = expr.Reduce(_ctx); Assert.That(Object.ReferenceEquals(ctx.Value, cell), Is.True); }
public void EvalDefinition_CreateSharedReference() { _env.Bind(Var.Bar, Value.Bar); var expr = BuiltIn.ListOf(ClSymbol.Define, Var.Foo, Var.Bar); Ignore(expr.Reduce(_ctx)); Assert.That(Object.ReferenceEquals(_env.Lookup(Var.Foo), _env.Lookup(Var.Bar)), Is.True); }
public void EvalDefinition_OverrideExistingBinding() { _env.Bind(Var.Foo, ClBool.True); var expr = BuiltIn.ListOf(ClSymbol.Define, Var.Foo, Value.Foo); var ctx = expr.Reduce(_ctx); Assert.That(ctx.Env.Lookup(Var.Foo), Is.EqualTo(Value.Foo)); }
public void EvalApplication_ThrowInvalidFunctionCall_WhenCarIsNotCallable() { _env.Bind(Var.Fn, Value.One); var expr = BuiltIn.ListOf(Var.Fn, Value.One); var errorMessage = $"{nameof(ClInt)} is neither callable nor special from"; Assert.That(() => expr.Reduce(_ctx), Throws.Exception.TypeOf <SyntaxError>().With.Message.EqualTo(errorMessage)); }
public void EvalApplication_ZeroArityFunction() { var constantFn = BuiltIn.ListOf(ClSymbol.Lambda, ClCell.Nil, Value.One); var expr = BuiltIn.ListOf(constantFn); var context = expr.Reduce(_ctx); Assert.That(context.Value, Is.EqualTo(Value.One)); }