automated commit TP3

This commit is contained in:
Rémi Di Guardia
2022-09-28 09:28:41 +02:00
parent 530ff7e694
commit 2e15c1352e
45 changed files with 1723 additions and 1 deletions
+178
View File
@@ -0,0 +1,178 @@
# Visitor to *interpret* MiniC files
from typing import Dict, List, cast
from MiniCVisitor import MiniCVisitor
from MiniCParser import MiniCParser
from Lib.Errors import MiniCRuntimeError, MiniCInternalError
MINIC_VALUE = int | str | bool | float | List['MINIC_VALUE']
class MiniCInterpretVisitor(MiniCVisitor):
_memory: Dict[str, MINIC_VALUE]
def __init__(self):
self._memory = dict() # store all variable ids and values.
self.has_main = False
# visitors for variable declarations
def visitVarDecl(self, ctx) -> None:
# Initialise all variables in self._memory
type_str = ctx.typee().getText()
raise NotImplementedError()
def visitIdList(self, ctx) -> List[str]:
raise NotImplementedError()
def visitIdListBase(self, ctx) -> List[str]:
return [ctx.ID().getText()]
# visitors for atoms --> value
def visitParExpr(self, ctx) -> MINIC_VALUE:
return self.visit(ctx.expr())
def visitIntAtom(self, ctx) -> int:
return int(ctx.getText())
def visitFloatAtom(self, ctx) -> float:
return float(ctx.getText())
def visitBooleanAtom(self, ctx) -> bool:
return ctx.getText() == "true"
def visitIdAtom(self, ctx) -> MINIC_VALUE:
raise NotImplementedError()
def visitStringAtom(self, ctx) -> str:
return ctx.getText()[1:-1] # Remove the ""
# visit expressions
def visitAtomExpr(self, ctx) -> MINIC_VALUE:
return self.visit(ctx.atom())
def visitOrExpr(self, ctx) -> bool:
lval = self.visit(ctx.expr(0))
rval = self.visit(ctx.expr(1))
return lval | rval
def visitAndExpr(self, ctx) -> bool:
lval = self.visit(ctx.expr(0))
rval = self.visit(ctx.expr(1))
return lval & rval
def visitEqualityExpr(self, ctx) -> bool:
assert ctx.myop is not None
lval = self.visit(ctx.expr(0))
rval = self.visit(ctx.expr(1))
# be careful for float equality
if ctx.myop.type == MiniCParser.EQ:
return lval == rval
else:
return lval != rval
def visitRelationalExpr(self, ctx) -> bool:
assert ctx.myop is not None
lval = self.visit(ctx.expr(0))
rval = self.visit(ctx.expr(1))
if ctx.myop.type == MiniCParser.LT:
return lval < rval
elif ctx.myop.type == MiniCParser.LTEQ:
return lval <= rval
elif ctx.myop.type == MiniCParser.GT:
return lval > rval
elif ctx.myop.type == MiniCParser.GTEQ:
return lval >= rval
else:
raise MiniCInternalError(
"Unknown comparison operator '%s'" % ctx.myop
)
def visitAdditiveExpr(self, ctx) -> MINIC_VALUE:
assert ctx.myop is not None
lval = self.visit(ctx.expr(0))
rval = self.visit(ctx.expr(1))
if ctx.myop.type == MiniCParser.PLUS:
if any(isinstance(x, str) for x in (lval, rval)):
return '{}{}'.format(lval, rval)
else:
return lval + rval
elif ctx.myop.type == MiniCParser.MINUS:
return lval - rval
else:
raise MiniCInternalError(
"Unknown additive operator '%s'" % ctx.myop)
def visitMultiplicativeExpr(self, ctx) -> MINIC_VALUE:
assert ctx.myop is not None
lval = self.visit(ctx.expr(0))
rval = self.visit(ctx.expr(1))
if ctx.myop.type == MiniCParser.MULT:
return lval * rval
elif ctx.myop.type == MiniCParser.DIV:
if rval == 0:
raise MiniCRuntimeError("Division by 0")
if isinstance(lval, int):
return lval // rval
else:
return lval / rval
elif ctx.myop.type == MiniCParser.MOD:
# TODO : interpret modulo
raise NotImplementedError()
else:
raise MiniCInternalError(
"Unknown multiplicative operator '%s'" % ctx.myop)
def visitNotExpr(self, ctx) -> bool:
return not self.visit(ctx.expr())
def visitUnaryMinusExpr(self, ctx) -> MINIC_VALUE:
return -self.visit(ctx.expr())
# visit statements
def visitPrintlnintStat(self, ctx) -> None:
val = self.visit(ctx.expr())
print(val)
def visitPrintlnfloatStat(self, ctx) -> None:
val = self.visit(ctx.expr())
if isinstance(val, float):
val = "%.2f" % val
print(val)
def visitPrintlnboolStat(self, ctx) -> None:
val = self.visit(ctx.expr())
print('1' if val else '0')
def visitPrintlnstringStat(self, ctx) -> None:
val = self.visit(ctx.expr())
print(val)
def visitAssignStat(self, ctx) -> None:
raise NotImplementedError()
def visitIfStat(self, ctx) -> None:
raise NotImplementedError()
def visitWhileStat(self, ctx) -> None:
raise NotImplementedError()
# TOPLEVEL
def visitProgRule(self, ctx) -> None:
self.visitChildren(ctx)
if not self.has_main:
# A program without a main function is compilable (hence
# it's not a typing error per se), but not executable,
# hence we consider it a runtime error.
raise MiniCRuntimeError("No main function in file")
# Visit a function: ignore if non main!
def visitFuncDef(self, ctx) -> None:
funname = ctx.ID().getText()
if funname == "main":
self.has_main = True
self.visit(ctx.vardecl_l())
self.visit(ctx.block())
+147
View File
@@ -0,0 +1,147 @@
# Visitor to *typecheck* MiniC files
from typing import List
from MiniCVisitor import MiniCVisitor
from MiniCParser import MiniCParser
from Lib.Errors import MiniCInternalError, MiniCTypeError
from enum import Enum
class BaseType(Enum):
Float, Integer, Boolean, String = range(4)
# Basic Type Checking for MiniC programs.
class MiniCTypingVisitor(MiniCVisitor):
def __init__(self):
self._memorytypes = dict() # id -> types
# For now, we don't have real functions ...
self._current_function = "main"
def _raise(self, ctx, for_what, *types):
raise MiniCTypeError(
'In function {}: Line {} col {}: invalid type for {}: {}'.format(
self._current_function,
ctx.start.line, ctx.start.column, for_what,
' and '.join(t.name.lower() for t in types)))
def _assertSameType(self, ctx, for_what, *types):
if not all(types[0] == t for t in types):
raise MiniCTypeError(
'In function {}: Line {} col {}: type mismatch for {}: {}'.format(
self._current_function,
ctx.start.line, ctx.start.column, for_what,
' and '.join(t.name.lower() for t in types)))
def _raiseNonType(self, ctx, message):
raise MiniCTypeError(
'In function {}: Line {} col {}: {}'.format(
self._current_function,
ctx.start.line, ctx.start.column, message))
# type declaration
def visitVarDecl(self, ctx) -> None:
raise NotImplementedError()
def visitBasicType(self, ctx):
assert ctx.mytype is not None
if ctx.mytype.type == MiniCParser.INTTYPE:
return BaseType.Integer
elif ctx.mytype.type == MiniCParser.FLOATTYPE:
return BaseType.Float
else: # TODO: same for other types
raise NotImplementedError()
def visitIdList(self, ctx) -> List[str]:
raise NotImplementedError()
def visitIdListBase(self, ctx) -> List[str]:
raise NotImplementedError()
# typing visitors for expressions, statements !
# visitors for atoms --> type
def visitParExpr(self, ctx):
return self.visit(ctx.expr())
def visitIntAtom(self, ctx):
return BaseType.Integer
def visitFloatAtom(self, ctx):
return BaseType.Float
def visitBooleanAtom(self, ctx):
raise NotImplementedError()
def visitIdAtom(self, ctx):
try:
return self._memorytypes[ctx.getText()]
except KeyError:
self._raiseNonType(ctx,
"Undefined variable {}".format(ctx.getText()))
def visitStringAtom(self, ctx):
return BaseType.String
# now visit expr
def visitAtomExpr(self, ctx):
return self.visit(ctx.atom())
def visitOrExpr(self, ctx):
raise NotImplementedError()
def visitAndExpr(self, ctx):
raise NotImplementedError()
def visitEqualityExpr(self, ctx):
raise NotImplementedError()
def visitRelationalExpr(self, ctx):
raise NotImplementedError()
def visitAdditiveExpr(self, ctx):
assert ctx.myop is not None
raise NotImplementedError()
def visitMultiplicativeExpr(self, ctx):
raise NotImplementedError()
def visitNotExpr(self, ctx):
raise NotImplementedError()
def visitUnaryMinusExpr(self, ctx):
raise NotImplementedError()
# visit statements
def visitPrintlnintStat(self, ctx):
etype = self.visit(ctx.expr())
if etype != BaseType.Integer:
self._raise(ctx, 'println_int statement', etype)
def visitPrintlnfloatStat(self, ctx):
etype = self.visit(ctx.expr())
if etype != BaseType.Float:
self._raise(ctx, 'println_float statement', etype)
def visitPrintlnboolStat(self, ctx):
etype = self.visit(ctx.expr())
if etype != BaseType.Boolean:
self._raise(ctx, 'println_int statement', etype)
def visitPrintlnstringStat(self, ctx):
etype = self.visit(ctx.expr())
if etype != BaseType.String:
self._raise(ctx, 'println_string statement', etype)
def visitAssignStat(self, ctx):
raise NotImplementedError()
def visitWhileStat(self, ctx):
raise NotImplementedError()
def visitIfStat(self, ctx):
raise NotImplementedError()
@@ -0,0 +1,13 @@
#include "printlib.h"
int main(){
int n;
n=17;
m=n+3;
println_int(m);
return 0;
}
// EXPECTED
// EXITCODE 2
// In function main: Line 6 col 2: Undefined variable m
@@ -0,0 +1,10 @@
#include "printlib.h"
int main(){
int x;
x="blablabla";
return 0;
}
// EXITCODE 2
// EXPECTED
// In function main: Line 5 col 2: type mismatch for x: integer and string
@@ -0,0 +1,14 @@
#include "printlib.h"
int main(){
int n;
string s;
n=17;
s="seventeen";
s = n*s;
return 0;
}
// EXITCODE 2
// EXPECTED
// In function main: Line 8 col 6: invalid type for multiplicative operands: integer and string
@@ -0,0 +1,11 @@
#include "printlib.h"
int main(){
string x;
x=1;
return 0;
}
// EXITCODE 2
// EXPECTED
// In function main: Line 5 col 2: type mismatch for x: string and integer
@@ -0,0 +1,10 @@
#include "printlib.h"
int main(){
int x;
x=34+f;
return 0;
}
// EXITCODE 2
// EXPECTED
// In function main: Line 5 col 7: Undefined variable f
@@ -0,0 +1,11 @@
#include "printlib.h"
int main(){
println_int("foo");
return 0;
}
// EXITCODE 2
// EXPECTED
// In function main: Line 4 col 2: invalid type for println_int statement: string
@@ -0,0 +1,9 @@
#include "printlib.h"
int main(){
println_int(true+true);
return 0;
}
// EXITCODE 2
// EXPECTED
// In function main: Line 4 col 14: invalid type for additive operands: boolean and boolean
@@ -0,0 +1,12 @@
#include "printlib.h"
int main(){
int x,y;
int z,x;
x=42;
return 0;
}
// EXITCODE 2
// EXPECTED
// In function main: Line 5 col 2: Variable x already declared
@@ -0,0 +1,11 @@
#include "printlib.h"
int toto(){
println_int(42);
return 0;
}
// EXITCODE 1
// EXPECTED
// No main function in file
@@ -0,0 +1,13 @@
#include "printlib.h"
int main()
{
int n,u;
n=17;
u=n;
println_int(n);
return 0;
}
// EXPECTED
// 17
@@ -0,0 +1,47 @@
#include "printlib.h"
int main()
{
if (2 < 3)
{
println_int(1);
}
if (2 > 3)
{
println_int(2);
}
if (2 <= 2)
{
println_int(3);
}
if (2 >= 2)
{
println_int(4);
}
if (2 == 3)
{
println_int(10);
}
if (2 != 3)
{
println_int(20);
}
if (2 == 2)
{
println_int(30);
}
if (2 != 2)
{
println_int(40);
}
return 0;
}
// EXPECTED
// 1
// 3
// 4
// 20
// 30
@@ -0,0 +1,11 @@
#include "printlib.h"
int main() {
if ((1.0 + 2.0) * 3.0 == 9.0) {
println_string("OK");
}
return 0;
}
// EXPECTED
// OK
@@ -0,0 +1,15 @@
#include "printlib.h"
int main(){
println_int(3/2+45*(2/1));
println_int(23+19);
println_bool( (false || 3 != 77 ) && (42<=1515) );
println_string("coucou");
return 0;
}
// EXPECTED
// 91
// 42
// 1
// coucou
@@ -0,0 +1,9 @@
#include "printlib.h"
int main(){
println_int(42);
return 0;
}
// EXPECTED
// 42
@@ -0,0 +1,11 @@
#include "printlib.h"
int main(){
int x;
x="blabla";
return 0;
}
// EXPECTED
// In function main: Line 5 col 2: type mismatch for x: integer and string
// EXITCODE 2
@@ -0,0 +1,14 @@
#include "printlib.h"
int main(){
string x,y,z;
x = "ENS";
y = "De Lyon";
z = x + " " + y;
println_string(z);
return 0;
}
// EXPECTED
// ENS De Lyon
@@ -0,0 +1,16 @@
#include "printlib.h"
int main(){
string n,m;
n = "foo";
m = "bar";
println_string(n);
println_string(m);
println_string(n + m);
return 0;
}
// EXPECTED
// foo
// bar
// foobar
@@ -0,0 +1,13 @@
#include "printlib.h"
int main() {
string s;
println_string(s);
s = s + "Coucou";
println_string(s);
return 0;
}
// EXPECTED
//
// Coucou
@@ -0,0 +1,16 @@
#include "printlib.h"
int main() {
bool x;
if (x) {
println_int(1);
}
x = !x;
if (x) {
println_int(2);
}
return 0;
}
// EXPECTED
// 2
@@ -0,0 +1,13 @@
#include "printlib.h"
int main() {
float x;
println_float(x);
x = x + 1.0;
println_float(x);
return 0;
}
// EXPECTED
// 0.00
// 1.00
@@ -0,0 +1,13 @@
#include "printlib.h"
int main() {
int x;
println_int(x);
x = x + 1;
println_int(x);
return 0;
}
// EXPECTED
// 0
// 1
+1
View File
@@ -0,0 +1 @@
Add your own tests in this directory.