public IErrorReporter ErrorSlicingOnDereference() { NameResolver resolver = null; foreach (var mutability in Options.AllMutabilityModes) { var env = Environment.Create(new Options() { AllowDereference = true }.SetMutability(mutability)); var root_ns = env.Root; Int64Literal rhs_value = IntLiteral.Create("80"); root_ns.AddBuilder(FunctionBuilder.Create( "foo", null, ExpressionReadMode.OptionalUse, NameFactory.UnitNameReference(), Block.CreateStatement( VariableDeclaration.CreateStatement("p", NameFactory.PointerNameReference(NameFactory.IObjectNameReference(TypeMutability.Reassignable)), Undef.Create()), // only with same type we have guarantee we won't use dereference as slicing tool, consider // x *Object ; (*x) = big_type_instance Assignment.CreateStatement(Dereference.Create(NameReference.Create("p")), rhs_value) ))); resolver = NameResolver.Create(env); Assert.AreEqual(1, resolver.ErrorManager.Errors.Count); Assert.IsTrue(resolver.ErrorManager.HasError(ErrorCode.TypeMismatch, rhs_value)); } return(resolver); }
public IErrorReporter ErrorEscapingReceivedReferenceFromFunction() { NameResolver resolver = null; foreach (var mutability in Options.AllMutabilityModes) { var env = Language.Environment.Create(new Options() { DiscardingAnyExpressionDuringTests = true } .SetMutability(mutability)); var root_ns = env.Root; root_ns.AddBuilder(FunctionBuilder.Create("selector", ExpressionReadMode.ReadRequired, NameFactory.ReferenceNameReference(NameFactory.IntNameReference()), Block.CreateStatement( ExpressionFactory.Readout("b"), Return.Create(NameReference.Create("a")) )) .Parameters( FunctionParameter.Create("a", NameFactory.ReferenceNameReference(NameFactory.IntNameReference())), FunctionParameter.Create("b", NameFactory.ReferenceNameReference(NameFactory.IntNameReference())))); FunctionCall call = FunctionCall.Create("selector", IntLiteral.Create("2"), IntLiteral.Create("3")); FunctionDefinition func = root_ns.AddBuilder(FunctionBuilder.Create("notimportant", ExpressionReadMode.OptionalUse, NameFactory.UnitNameReference(), Block.CreateStatement( VariableDeclaration.CreateStatement("h", NameFactory.ReferenceNameReference(NameFactory.IntNameReference()), IntLiteral.Create("0"), EntityModifier.Reassignable), Block.CreateStatement( // error: the most alive reference the function can return is limited to this scope // so it cannot be assigned to outer-scope variable Assignment.CreateStatement(NameReference.Create("h"), call) ), ExpressionFactory.Readout("h") ))); resolver = NameResolver.Create(env); Assert.AreEqual(1, resolver.ErrorManager.Errors.Count); Assert.IsTrue(resolver.ErrorManager.HasError(ErrorCode.EscapingReference, call)); } return(resolver); }
public IInterpreter ResolvingGenericArgumentInRuntime() { var interpreter = new Interpreter.Interpreter(); foreach (var mutability in Options.AllMutabilityModes) { var env = Environment.Create(new Options() { DebugThrowOnError = true }.SetMutability(mutability)); var root_ns = env.Root; root_ns.AddBuilder(FunctionBuilder.Create("oracle", "O", VarianceMode.None, NameFactory.BoolNameReference(), Block.CreateStatement( Return.Create(IsType.Create(NameReference.Create("thing"), NameReference.Create("O"))) )) .Parameters(FunctionParameter.Create("thing", NameFactory.ReferenceNameReference(NameFactory.IObjectNameReference())))); root_ns.AddBuilder(FunctionBuilder.Create( "main", ExpressionReadMode.OptionalUse, NameFactory.Nat8NameReference(), Block.CreateStatement( VariableDeclaration.CreateStatement("acc", null, Nat8Literal.Create("0"), env.Options.ReassignableModifier()), VariableDeclaration.CreateStatement("i", null, ExpressionFactory.HeapConstructor(NameFactory.IntNameReference(), IntLiteral.Create("7"))), VariableDeclaration.CreateStatement("d", null, ExpressionFactory.HeapConstructor(NameFactory.RealNameReference(), RealLiteral.Create("3.3"))), IfBranch.CreateIf(FunctionCall.Create(NameReference.Create("oracle", NameFactory.IntNameReference()), NameReference.Create("i")), new[] { ExpressionFactory.IncBy("acc", Nat8Literal.Create("2")) }), IfBranch.CreateIf(FunctionCall.Create(NameReference.Create("oracle", NameFactory.IntNameReference()), NameReference.Create("d")), new[] { ExpressionFactory.IncBy("acc", Nat8Literal.Create("88")) }), Return.Create(NameReference.Create("acc")) ))); ExecValue result = interpreter.TestRun(env); Assert.AreEqual((byte)2, result.RetValue.PlainValue); } return(interpreter); }
public IInterpreter ShortcutComputationInOptionalDeclaration() { var interpreter = new Interpreter.Interpreter(); foreach (var mutability in Options.AllMutabilityModes) { // purpose: check if RHS of the optional declaration is computed only when it is needed // here we count RHS computations and since we declare two variables // let (x,y) =? (None,Some) // Some should not be executed, because `x` assigment fails first var env = Language.Environment.Create(new Options() { DebugThrowOnError = true, DiscardingAnyExpressionDuringTests = true, }.SetMutability(mutability)); var root_ns = env.Root; root_ns.AddBuilder(TypeBuilder.Create("Mutator") .SetModifier(EntityModifier.Mutable) .With(VariableDeclaration.CreateStatement("c", NameFactory.IntNameReference(), null, env.Options.ReassignableModifier() | EntityModifier.Public))); // return Some or None depending on the `f` parameter, and also increments the count of option evaluations root_ns.AddBuilder(FunctionBuilder.Create("give", NameFactory.OptionNameReference(NameFactory.Nat8NameReference()), Block.CreateStatement( ExpressionFactory.Inc(() => NameReference.Create("m", "c")), Return.Create(ExpressionFactory.Ternary(NameReference.Create("f"), ExpressionFactory.OptionOf(NameFactory.Nat8NameReference(), Nat8Literal.Create("11")), ExpressionFactory.OptionEmpty(NameFactory.Nat8NameReference()))) )) .Parameters(FunctionParameter.Create("f", NameFactory.BoolNameReference()), FunctionParameter.Create("m", NameFactory.ReferenceNameReference(NameReference.Create("Mutator"))))); IExpression opt_declaration = ExpressionFactory.OptionalDeclaration(new[] { VariablePrototype.Create("x", NameFactory.Nat8NameReference()), VariablePrototype.Create("y", NameFactory.Nat8NameReference()) }, new[] { FunctionCall.Create("give", BoolLiteral.CreateFalse(), NameReference.Create("mut")), FunctionCall.Create("give", BoolLiteral.CreateTrue(), NameReference.Create("mut")), }); root_ns.AddBuilder(FunctionBuilder.Create("main", ExpressionReadMode.OptionalUse, NameFactory.Nat8NameReference(), Block.CreateStatement( VariableDeclaration.CreateStatement("mut", null, ExpressionFactory.StackConstructor(NameReference.Create("Mutator"))), IfBranch.CreateIf(opt_declaration, new[] { ExpressionFactory.Readout("x"), ExpressionFactory.Readout("y"), ExpressionFactory.GenericThrow(), }, IfBranch.CreateElse( // crucial check -- we should not evaluate the second option ExpressionFactory.AssertEqual(IntLiteral.Create("1"), NameReference.Create("mut", "c")) )), Return.Create(Nat8Literal.Create("0")) ))); ExecValue result = interpreter.TestRun(env); Assert.AreEqual((byte)0, result.RetValue.PlainValue); } return(interpreter); }
public IErrorReporter ErrorAttachmentObjectOnStackAndHeap() { NameResolver resolver = null; foreach (var mutability in Options.AllMutabilityModes) { var env = Language.Environment.Create(new Options() { DiscardingAnyExpressionDuringTests = true } .SetMutability(mutability)); var root_ns = env.Root; root_ns.AddBuilder(TypeBuilder.Create("Keeper") .With(VariableDeclaration.CreateStatement("world", NameFactory.PointerNameReference(NameFactory.IntNameReference()), Undef.Create(), EntityModifier.Public)) .With(FunctionBuilder.CreateInitConstructor(Block.CreateStatement( Assignment.CreateStatement(NameReference.CreateThised("world"), NameReference.Create("in_value")) )) .Parameters(FunctionParameter.Create("in_value", NameFactory.PointerNameReference(NameFactory.IntNameReference()))))); IExpression stack_init_value = ExpressionFactory.StackConstructor("Keeper", NameReference.Create("i")); IExpression heap_init_value = ExpressionFactory.HeapConstructor("Keeper", NameReference.Create("i")); FunctionDefinition func = root_ns.AddBuilder(FunctionBuilder.Create("notimportant", ExpressionReadMode.OptionalUse, NameFactory.UnitNameReference(), Block.CreateStatement( VariableDeclaration.CreateStatement("i", NameFactory.ReferenceNameReference(NameFactory.IntNameReference()), IntLiteral.Create("0"), EntityModifier.Reassignable), // this is incorrect, because we are creating attachment object as value, dropping the lifetime VariableDeclaration.CreateStatement("attach1", NameReference.Create("Keeper"), stack_init_value), ExpressionFactory.Readout("attach1"), // this is incorrect, because we are creating attachment object as global instance, dropping the lifetime VariableDeclaration.CreateStatement("attach2", NameFactory.PointerNameReference(NameReference.Create("Keeper")), heap_init_value), ExpressionFactory.Readout("attach2") ))); resolver = NameResolver.Create(env); Assert.IsTrue(resolver.ErrorManager.HasError(ErrorCode.EscapingReference, stack_init_value)); Assert.IsTrue(resolver.ErrorManager.HasError(ErrorCode.EscapingReference, heap_init_value)); Assert.AreEqual(2, resolver.ErrorManager.Errors.Count); } return(resolver); }
public IErrorReporter ErrorStoredLocalReferenceEscapesFromFunction() { NameResolver resolver = null; foreach (var mutability in Options.AllMutabilityModes) { var env = Language.Environment.Create(new Options() { }.SetMutability(mutability)); var root_ns = env.Root; Return ret = Return.Create(NameReference.Create("o")); FunctionDefinition func = root_ns.AddBuilder(FunctionBuilder.Create("notimportant", ExpressionReadMode.OptionalUse, NameFactory.OptionNameReference(NameFactory.ReferenceNameReference(NameFactory.IntNameReference())), Block.CreateStatement( VariableDeclaration.CreateStatement("h", null, IntLiteral.Create("3")), VariableDeclaration.CreateStatement("o", null, ExpressionFactory.StackConstructor( NameFactory.OptionNameReference(NameFactory.ReferenceNameReference(NameFactory.IntNameReference())), NameReference.Create("h"))), // error, we would effectively escape with reference to local variable ret ))); resolver = NameResolver.Create(env); Assert.AreEqual(1, resolver.ErrorManager.Errors.Count); Assert.IsTrue(resolver.ErrorManager.HasError(ErrorCode.EscapingReference, ret.Expr)); } return(resolver); }
public IErrorReporter ErrorEscapingReferenceWithAttachmentObject() { NameResolver resolver = null; foreach (var mutability in Options.AllMutabilityModes) { var env = Language.Environment.Create(new Options() { DiscardingAnyExpressionDuringTests = true } .SetMutability(mutability)); var root_ns = env.Root; root_ns.AddBuilder(TypeBuilder.Create("Keeper") .With(VariableDeclaration.CreateStatement("world", NameFactory.PointerNameReference(NameFactory.IntNameReference()), Undef.Create(), EntityModifier.Public)) .With(FunctionBuilder.CreateInitConstructor(Block.CreateStatement( Assignment.CreateStatement(NameReference.CreateThised("world"), NameReference.Create("in_value")) )) .Parameters(FunctionParameter.Create("in_value", NameFactory.PointerNameReference(NameFactory.IntNameReference()))))); Assignment assign = Assignment.CreateStatement(NameReference.Create("attach"), ExpressionFactory.StackConstructor("Keeper", NameReference.Create("i"))).Cast <Assignment>(); FunctionDefinition func = root_ns.AddBuilder(FunctionBuilder.Create("notimportant", ExpressionReadMode.OptionalUse, NameFactory.UnitNameReference(), Block.CreateStatement( VariableDeclaration.CreateStatement("attach", NameReference.Create("Keeper"), Undef.Create(), EntityModifier.Reassignable), Block.CreateStatement( VariableDeclaration.CreateStatement("i", NameFactory.ReferenceNameReference(NameFactory.IntNameReference()), IntLiteral.Create("0")), // cannot execute this assignment because the reference would move from here to outer scope // just wrapped in `Keeper` instance // please note this `Keeper` instance is attached to `i` // (triggered by conversion reference->pointer in constructor), so it cannot outlive it assign, ExpressionFactory.Readout("attach") ) ))); resolver = NameResolver.Create(env); Assert.AreEqual(1, resolver.ErrorManager.Errors.Count); Assert.IsTrue(resolver.ErrorManager.HasError(ErrorCode.EscapingReference, assign.RhsValue)); } return(resolver); }
public IErrorReporter ErrorEscapingReceivedReferenceFromField() { NameResolver resolver = null; foreach (var mutability in Options.AllMutabilityModes) { var env = Language.Environment.Create(new Options() { DiscardingAnyExpressionDuringTests = true } .SetMutability(mutability)); var root_ns = env.Root; root_ns.AddBuilder(TypeBuilder.Create("Keeper") .With(VariableDeclaration.CreateStatement("world", NameFactory.IntNameReference(), null, EntityModifier.Public))); NameReference heap_field_ref = NameReference.Create("h", "world"); NameReference stack_field_ref = NameReference.Create("s", "world"); FunctionDefinition func = root_ns.AddBuilder(FunctionBuilder.Create("notimportant", ExpressionReadMode.OptionalUse, NameFactory.UnitNameReference(), Block.CreateStatement( VariableDeclaration.CreateStatement("i", NameFactory.ReferenceNameReference(NameFactory.IntNameReference()), IntLiteral.Create("0"), EntityModifier.Reassignable), VariableDeclaration.CreateStatement("h", null, ExpressionFactory.HeapConstructor("Keeper")), Block.CreateStatement( VariableDeclaration.CreateStatement("s", null, ExpressionFactory.StackConstructor("Keeper")), Assignment.CreateStatement(NameReference.Create("i"), heap_field_ref), Assignment.CreateStatement(NameReference.Create("i"), stack_field_ref) ), ExpressionFactory.Readout("i") ))); resolver = NameResolver.Create(env); Assert.IsTrue(resolver.ErrorManager.HasError(ErrorCode.EscapingReference, heap_field_ref)); Assert.IsTrue(resolver.ErrorManager.HasError(ErrorCode.EscapingReference, stack_field_ref)); Assert.AreEqual(2, resolver.ErrorManager.Errors.Count); } return(resolver); }
public IErrorReporter ErrorSettingCustomGetter() { NameResolver resolver = null; foreach (var mutability in Options.AllMutabilityModes) { var env = Environment.Create(new Options() { }.SetMutability(mutability)); var root_ns = env.Root; // we can assign property using getter (only in constructor) but getter has to be auto-generated, // here it is custom code, thus it is illegal IExpression assign = Assignment.CreateStatement(NameReference.CreateThised("x"), IntLiteral.Create("3")); root_ns.AddBuilder(TypeBuilder.Create("Point") .SetModifier(EntityModifier.Mutable) .With(PropertyBuilder.Create(env.Options, "x", () => NameFactory.IntNameReference()) .WithGetter(Block.CreateStatement(Return.Create(IntLiteral.Create("5"))))) .With(FunctionBuilder.CreateInitConstructor(Block.CreateStatement( assign )))); resolver = NameResolver.Create(env); Assert.AreEqual(1, resolver.ErrorManager.Errors.Count); Assert.IsTrue(resolver.ErrorManager.HasError(ErrorCode.CannotAssignCustomProperty, assign)); } return(resolver); }