Exemplo n.º 1
0
            // the expected return type of the operation
            override public ValueType Type(MiniPL.Runnable context)
            {
                switch (op)
                {
                case '+':
                    ValueType t = lhs.Type(context);
                    if (t == ValueType.String)
                    {
                        return(t);
                    }
                    return(ValueType.Integer);

                case '-':
                    return(ValueType.Integer);

                case '*':
                    return(ValueType.Integer);

                case '/':
                    return(ValueType.Integer);

                case '<':
                    return(ValueType.Boolean);

                case '=':
                    return(ValueType.Boolean);

                case '&':
                    return(ValueType.Boolean);

                default:
                    throw new Exception("UNEXPECTER OPERATOR " + op);
                }
            }
Exemplo n.º 2
0
            public override void TypeCheck(MiniPL.Runnable context)
            {
                // typecheck value
                expr.TypeCheck(context);
                // check that value type matches variable
                switch (context.declarations[identifier].Type)
                {
                case ValueType.Boolean:
                    if (expr.Type(context) == ValueType.String)
                    {
                        context.errors.Add(new SemanticError(Token, "cannot assign string value to boolean " + identifier));
                    }
                    break;

                case ValueType.Integer:
                    if (expr.Type(context) != ValueType.Integer)
                    {
                        context.errors.Add(new SemanticError(Token, "expected integer type value for " + identifier));
                    }
                    break;

                case ValueType.String:
                    if (expr.Type(context) != ValueType.String)
                    {
                        context.errors.Add(new SemanticError(Token, "expected string type value for " + identifier));
                    }
                    break;
                }
            }
Exemplo n.º 3
0
 // Mini-PL spec only defines reading integer and string values
 public override void TypeCheck(MiniPL.Runnable context)
 {
     if (context.declarations[identifier].Type == ValueType.Boolean)
     {
         context.errors.Add(new SemanticError(Token, "cannot read a boolean value"));
     }
 }
Exemplo n.º 4
0
            public override void TypeCheck(MiniPL.Runnable context)
            {
                // if initial value specified check it agaist the type
                if (initialValue != null)
                {
                    initialValue.TypeCheck(context);
                    switch (type)
                    {
                    case ValueType.Boolean:
                        if (initialValue.Type(context) == ValueType.String)
                        {
                            context.errors.Add(new SemanticError(Token, "cannot assign string value to boolean " + identifier));
                        }
                        break;

                    case ValueType.Integer:
                        if (initialValue.Type(context) != ValueType.Integer)
                        {
                            context.errors.Add(new SemanticError(Token, "expected integer type value for " + identifier));
                        }
                        break;

                    case ValueType.String:
                        if (initialValue.Type(context) != ValueType.String)
                        {
                            context.errors.Add(new SemanticError(Token, "expected string type value for " + identifier));
                        }
                        break;
                    }
                }
            }
Exemplo n.º 5
0
            // recursively check operands and check that their types are compatible with operation
            override public void TypeCheck(MiniPL.Runnable context)
            {
                rhs.TypeCheck(context);
                lhs.TypeCheck(context);
                switch (op)
                {
                case '+':
                    if (!((rhs.Type(context) == ValueType.Integer && lhs.Type(context) == ValueType.Integer) ||
                          (rhs.Type(context) == ValueType.String && lhs.Type(context) == ValueType.String)))
                    {
                        context.errors.Add(new SemanticError(Token, "bad operand types for '+' operation"));
                    }
                    break;

                case '-':
                    if (!(rhs.Type(context) == ValueType.Integer && lhs.Type(context) == ValueType.Integer))
                    {
                        context.errors.Add(new SemanticError(Token, "bad operand types for '-' operation"));
                    }
                    break;

                case '*':
                    if (!(rhs.Type(context) == ValueType.Integer && lhs.Type(context) == ValueType.Integer))
                    {
                        context.errors.Add(new SemanticError(Token, "bad operand types for '*' operation"));
                    }
                    break;

                case '/':
                    if (!(rhs.Type(context) == ValueType.Integer && lhs.Type(context) == ValueType.Integer))
                    {
                        context.errors.Add(new SemanticError(Token, "bad operand types for '/' operation"));
                    }
                    break;

                case '<':
                    if (!(rhs.Type(context) == ValueType.Integer && lhs.Type(context) == ValueType.Integer))
                    {
                        context.errors.Add(new SemanticError(Token, "bad operand types for '<' operation"));
                    }
                    break;

                case '=':
                    if (!(rhs.Type(context) == lhs.Type(context)))
                    {
                        context.errors.Add(new SemanticError(Token, "bad operand types for '=' operation"));
                    }
                    break;

                case '&':
                    if (rhs.Type(context) == ValueType.String || lhs.Type(context) == ValueType.String)
                    {
                        context.errors.Add(new SemanticError(Token, "bad operand types for '&' operation"));
                    }
                    break;
                }
            }
Exemplo n.º 6
0
 override public void TypeCheck(MiniPL.Runnable context)
 {
     expr.TypeCheck(context);
     if (expr.Type(context) != ValueType.Boolean &&
         expr.Type(context) != ValueType.Integer)
     {
         context.errors.Add(new SemanticError(Token, "bad type for '!' operation"));
     }
 }
Exemplo n.º 7
0
 public override void TypeCheck(MiniPL.Runnable context)
 {
     // typecheck parameter
     expr.TypeCheck(context);
     // Mini-PL spec only defines print for integer and boolean values
     if (expr.Type(context) == ValueType.Boolean)
     {
         context.errors.Add(new SemanticError(Token, "cannot print a boolean value"));
     }
 }
Exemplo n.º 8
0
 public override void TypeCheck(MiniPL.Runnable context)
 {
     // typecheck parameter
     expr.TypeCheck(context);
     // only defined for boolean parameter, but we'll allow integers too..
     if (expr.Type(context) == ValueType.String)
     {
         context.errors.Add(new SemanticError(Token, "cannot assert a string value"));
     }
 }
Exemplo n.º 9
0
 public override RuntimeError Execute(MiniPL.Runnable context, TextReader stdin, TextWriter stdout)
 {
     if (expr.Type(context) == ValueType.String)
     {
         throw new Exception("TYPE CHECKING FAILED");
     }
     // if expression evaluates to false, stop execution with a runtime error
     if (expr.Evaluate(context).BooleanValue() == false)
     {
         return(new RuntimeError(Token, "assertion failed"));
     }
     return(null);
 }
Exemplo n.º 10
0
 override public Value Evaluate(MiniPL.Runnable context)
 {
     if (op == '!')
     {
         if (expr.Type(context) == ValueType.Boolean)
         {
             return(new Value(!expr.Evaluate(context).BooleanValue()));
         }
         if (expr.Type(context) == ValueType.Integer)
         {
             return(new Value(expr.Evaluate(context).IntValue() == 0));
         }
         throw new Exception("TYPE CHECKING FAILED");
     }
     throw new Exception("UNEXPECTED OPERATION " + op);
 }
Exemplo n.º 11
0
            public override RuntimeError Execute(MiniPL.Runnable context, TextReader stdin, TextWriter stdout)
            {
                // print value of parameter to output stream
                switch (expr.Type(context))
                {
                case ValueType.Integer:
                    stdout.Write(expr.Evaluate(context).IntValue());
                    break;

                case ValueType.String:
                    stdout.Write(expr.Evaluate(context).StringValue());
                    break;

                default:
                    throw new Exception("TYPE CHECK FAILED");
                }
                return(null);
            }
Exemplo n.º 12
0
            // Execute read statement
            public override RuntimeError Execute(MiniPL.Runnable context, TextReader stdin, TextWriter stdout)
            {
                // read whitespace-delimited token from input stream
                string input = "";

                char[] buf = new char[1];

                // works well enough for console input but surely there's a better way..
                while (true)
                {
                    int read = stdin.Read(buf, 0, 1);
                    if (read == 0)
                    {
                        break;
                    }
                    if (buf[0] == ' ' || buf[0] == '\t' || buf[0] == '\n')
                    {
                        break;
                    }
                    input += buf[0];
                }

                if (context.declarations[identifier].Type == ValueType.Integer)
                {
                    // if expecting integer but parsing fails, create runtime error
                    int inputInt = 0;
                    if (!Int32.TryParse(input, out inputInt))
                    {
                        return(new RuntimeError(Token, "expected to read integer"));
                    }
                    context.values[identifier] = new Value(inputInt);
                }
                else if (context.declarations[identifier].Type == ValueType.String)
                {
                    context.values[identifier] = new Value(input);
                }
                else
                {
                    throw new Exception("TYPE CHECKING FAILED");
                }

                return(null);
            }
Exemplo n.º 13
0
            public override RuntimeError Execute(MiniPL.Runnable context, TextReader stdin, TextWriter stdout)
            {
                // execute all statements in block for every value of control variable from
                // value of start expression to value of end expression (inclusive)

                int start = startVal.Evaluate(context).IntValue();
                int end   = endVal.Evaluate(context).IntValue();

                for (int i = start; i <= end; i++)
                {
                    context.values[identifier] = new Value(i);
                    foreach (Statement stmt in block)
                    {
                        stmt.Execute(context, stdin, stdout);
                    }
                }
                // sample code seemed to indicate control value should be end + 1 after execution
                context.values[identifier] = new Value(end + 1);
                return(null);
            }
Exemplo n.º 14
0
 public override void TypeCheck(MiniPL.Runnable context)
 {
     // typecheck parameters, control variable, and every statement in loop
     startVal.TypeCheck(context);
     endVal.TypeCheck(context);
     if (context.declarations[identifier].Type != ValueType.Integer)
     {
         context.errors.Add(new SemanticError(Token, "bad for-loop control type"));
     }
     if (startVal.Type(context) != ValueType.Integer)
     {
         context.errors.Add(new SemanticError(startVal.Token, "bad for-loop start value type"));
     }
     if (endVal.Type(context) != ValueType.Integer)
     {
         context.errors.Add(new SemanticError(startVal.Token, "bad for-loop end value type"));
     }
     foreach (Statement stmt in block)
     {
         stmt.TypeCheck(context);
     }
 }
Exemplo n.º 15
0
 override public ValueType Type(MiniPL.Runnable context)
 {
     return(value.Type());
 }
Exemplo n.º 16
0
 override public ValueType Type(MiniPL.Runnable context)
 {
     return(ValueType.Boolean);
 }
Exemplo n.º 17
0
 public abstract ValueType Type(MiniPL.Runnable context);
Exemplo n.º 18
0
 public abstract Value Evaluate(MiniPL.Runnable context);
Exemplo n.º 19
0
 public override RuntimeError Execute(MiniPL.Runnable context, TextReader stdin, TextWriter stdout)
 {
     // just update symbol table
     context.values[identifier] = expr.Evaluate(context);
     return(null);
 }
Exemplo n.º 20
0
 override public void TypeCheck(MiniPL.Runnable context)
 {
     // nothing to check
 }
Exemplo n.º 21
0
 override public ValueType Type(MiniPL.Runnable context)
 {
     return(context.declarations[identifier].Type);
 }
Exemplo n.º 22
0
 public abstract void TypeCheck(MiniPL.Runnable context);
Exemplo n.º 23
0
 public override RuntimeError Execute(MiniPL.Runnable context, TextReader stdin, TextWriter stdout)
 {
     // update symbol table to default or specified initial value
     context.values[identifier] = (initialValue == null) ? new Value(type) : initialValue.Evaluate(context);
     return(null);
 }
Exemplo n.º 24
0
            // apply the appropriate operation on operands
            override public Value Evaluate(MiniPL.Runnable context)
            {
                switch (op)
                {
                case '+':
                    if (rhs.Type(context) == ValueType.Integer && lhs.Type(context) == ValueType.Integer)
                    {
                        return(new Value(lhs.Evaluate(context).IntValue() + rhs.Evaluate(context).IntValue()));
                    }
                    if (rhs.Type(context) == ValueType.String && lhs.Type(context) == ValueType.String)
                    {
                        return(new Value(lhs.Evaluate(context).StringValue() + rhs.Evaluate(context).StringValue()));
                    }
                    throw new Exception("TYPECHECKING FAILED");

                case '-':
                    if (rhs.Type(context) != ValueType.Integer || lhs.Type(context) != ValueType.Integer)
                    {
                        throw new Exception("TYPECHECKING FAILED");
                    }
                    return(new Value(lhs.Evaluate(context).IntValue() - rhs.Evaluate(context).IntValue()));

                case '*':
                    if (rhs.Type(context) != ValueType.Integer || lhs.Type(context) != ValueType.Integer)
                    {
                        throw new Exception("TYPECHECKING FAILED");
                    }
                    return(new Value(lhs.Evaluate(context).IntValue() * rhs.Evaluate(context).IntValue()));

                case '/':
                    if (rhs.Type(context) != ValueType.Integer || lhs.Type(context) != ValueType.Integer)
                    {
                        throw new Exception("TYPECHECKING FAILED");
                    }
                    int denominator = rhs.Evaluate(context).IntValue();
                    if (denominator == 0)
                    {
                        throw new MiniPL_DivideByZeroException(new RuntimeError(Token, "divide by zero"));
                    }
                    return(new Value(lhs.Evaluate(context).IntValue() / denominator));

                case '<':
                    if (rhs.Type(context) != ValueType.Integer || lhs.Type(context) != ValueType.Integer)
                    {
                        throw new Exception("TYPECHECKING FAILED");
                    }
                    return(new Value(lhs.Evaluate(context).IntValue() < rhs.Evaluate(context).IntValue()));

                case '=':
                    if (rhs.Type(context) != lhs.Type(context))
                    {
                        throw new Exception("TYPECHECKING FAILED");
                    }
                    switch (rhs.Type(context))
                    {
                    case ValueType.Boolean:
                        return(new Value(rhs.Evaluate(context).BooleanValue() == lhs.Evaluate(context).BooleanValue()));

                    case ValueType.Integer:
                        return(new Value(rhs.Evaluate(context).IntValue() == lhs.Evaluate(context).IntValue()));

                    case ValueType.String:
                        return(new Value(rhs.Evaluate(context).StringValue() == lhs.Evaluate(context).StringValue()));
                    }
                    break;

                case '&':
                    if (rhs.Type(context) == ValueType.String ||
                        lhs.Type(context) == ValueType.String)
                    {
                        throw new Exception("TYPECHECKING FAILED");
                    }
                    return(new Value(rhs.Evaluate(context).BooleanValue() && lhs.Evaluate(context).BooleanValue()));
                }
                throw new Exception("UNEXPECTED OPERATOR " + op);
            }
Exemplo n.º 25
0
 override public Value Evaluate(MiniPL.Runnable context)
 {
     return(context.values[identifier]);
 }
Exemplo n.º 26
0
 override public Value Evaluate(MiniPL.Runnable context)
 {
     return(value);
 }
Exemplo n.º 27
0
 public abstract RuntimeError Execute(MiniPL.Runnable context, TextReader stdin, TextWriter stdout);