protected override BaseExpression Visit(Decrement dec) { var t = _types.TypeOf(dec.Name); if (t != Execution.Type.Number) { return(base.Visit(dec)); } else { return(new Subtract(new Variable(dec.Name), new ConstantNumber((Number)1))); } }
private Type VariableRead(VariableName name) { var t = _types.TypeOf(name); if (t.HasValue) { return(t.Value); } if (name.IsExternal) { return(Type.String | Type.Number); } else { return(_types.TypeOf(name) ?? Type.Unassigned); } }
protected override BaseStatement Visit(CompoundAssignment compAss) { if (compAss.Op != Grammar.YololBinaryOp.Add && compAss.Op != Grammar.YololBinaryOp.Subtract) { return(base.Visit(compAss)); } if (!compAss.Expression.IsConstant) { return(base.Visit(compAss)); } // if right side cannot be evaluated then we can't compress it var right = compAss.Expression.TryStaticEvaluate(); if (!right.HasValue) { return(base.Visit(compAss)); } var type = _types.TypeOf(compAss.Left); switch (type) { default: case null: case Type.Error: case Type.Unassigned: return(base.Visit(compAss)); case Type.Number: { if (right != 1) { return(base.Visit(compAss)); } if (compAss.Op == Grammar.YololBinaryOp.Add) { return(new Assignment(compAss.Left, new Increment(compAss.Left))); } else { return(new Assignment(compAss.Left, new Decrement(compAss.Left))); } } case Type.String: { if (right != " " || compAss.Op != Grammar.YololBinaryOp.Add) { return(base.Visit(compAss)); } return(new Assignment(compAss.Left, new Increment(compAss.Left))); } } }
private Type DiscoverType(BaseExpression expr) { if (expr is ConstantNumber) { return(Type.Number); } if (expr is ConstantString) { return(Type.String); } if (expr is Variable var) { return(_types.TypeOf(var.Name) ?? Type.Unassigned); } return(Type.Unassigned); }
protected override BaseStatement Visit(If @if) { // Make sure true branch contains: // - A statement // - Which is an assignment // - To a number typed variable // - Variable is not external if (@if.TrueBranch.Statements.Count > 1) { return(base.Visit(@if)); } if (!(@if.TrueBranch.Statements.SingleOrDefault() is Assignment trueAss)) { return(base.Visit(@if)); } if (_types.TypeOf(trueAss.Left) != Execution.Type.Number) { return(base.Visit(@if)); } if (trueAss.Left.IsExternal) { return(base.Visit(@if)); } // Make sure the condition is something that returns `0` or `1` // If the `condition` is not in this form already then replace it with `condition != 0` var condition = @if.Condition.IsBoolean ? new Bracketed(@if.Condition) : new Bracketed(new NotEqualTo(new Bracketed(@if.Condition), new ConstantNumber(0))); if (@if.FalseBranch.Statements.Count == 0) { // Replace: // `if cond then a = v1 end` // With // `a += (v1 - a) * cond return(new CompoundAssignment(trueAss.Left, Grammar.YololBinaryOp.Add, new Multiply(new Bracketed(new Subtract(new Bracketed(trueAss.Right), new Variable(trueAss.Left))), condition))); } else { // todo: implement false branch throw new NotImplementedException(); //if (@if.FalseBranch.Statements.Count != 1) // return base.Visit(@if); //if (!(@if.FalseBranch.Statements.Single() is Assignment falseAss)) // return base.Visit(@if); //if (trueAss.Left.Name != falseAss.Left.Name) // return base.Visit(@if); //var falseRight = falseAss.Right.StaticEvaluate(); //if (falseRight.Type != Execution.Type.Number) // return base.Visit(@if); //// Replace: //// `if cond then a = v1 else a = v2 end` //// With //// `a = v2 + (v1 - v2) * cond ////b = 3 if a == 0 then b = 5 else b = 10 end //var diff = new Subtract(new ConstantNumber(trueRight.Number), new ConstantNumber(falseRight.Number)); //var diffEval = diff.StaticEvaluate(); //var finalRight = diffEval.Number == 1 ? (BaseExpression)condition : new Bracketed(new Multiply(new ConstantNumber(diffEval.Number), condition)); //return new Assignment(trueAss.Left, new Add(new ConstantNumber(falseRight.Number), finalRight)); } }