master
billsun 1 year ago
parent ebae52c4df
commit 1c282af443

@ -0,0 +1,6 @@
def hello(x:Int) =
new Array[Int](x + getchar());
val arr = hello(5);
arr(0) = toInt('H'); arr(1) = toInt('e'); arr(2) = toInt('l'); arr(3) = toInt('l'); arr(4) = toInt('o');
putchar(arr(3));putchar(arr(4));putchar(arr(2));arr(0)

@ -0,0 +1,17 @@
def even(x: Int) : Boolean =
toInt(toChar(x * 128)) == 0;
def pow(x: Int, y: Int): Int =
if (y == 0) 1
else if (even(y)) {
val t = pow(x, y / 2);
t*t
} else {
x * pow(x, y - 1)
};
var i = 30; var res = 0;
while(i > 0) {
res = res + pow(2, i);
i = i - 1; ()
};
res

@ -0,0 +1,7 @@
var x = 2;
var y = 0;
while ({ if (y < 3) true else y < 4}) {
x = x * x;
y = y + 1; ()
};
x

@ -350,7 +350,9 @@ abstract class X86Compiler extends BugReporter with Codegen {
val fLoc: String = fun match {
case Ref(fname) =>
env(fname) match {
case Reg(sp) => s"*${loc(sp)}" // Extra credit
case Reg(sp) =>
emitln(s"movq ${loc(sp)}, %rax")
s"*%rax" // Extra credit
case Func(name) => funcName(name) // TODO
}
case _ => // return from another invocation
@ -384,11 +386,10 @@ abstract class X86Compiler extends BugReporter with Codegen {
// the assembly variable "heap" contains a pointer to the first valid byte
// in the heap. Make sure to update its value accordingly.
// TODO
emitln(s"movq (%rip), ${loc(sp)}")
emitln(s"movq heap, ${loc(sp)}")
trans(size, sp + 1)(env)
emitln(s"movq (%rip), ${loc(sp + 2)}")
emitln(s"movq (${loc(sp + 2)}, ${loc(sp + 1)}, 8), ${loc(sp + 2)}")
emitln(s"movq ${loc(sp + 2)}, %rip")
emitln(s"shlq $$3, ${loc(sp + 1)}")
emitln(s"addq ${loc(sp + 1)}, heap")
case _ => BUG(s"don't know how to implement $exp")
}
}

@ -41,6 +41,7 @@ OPTION: intStack""")
} else {
args(0)
}
//val src = "var x = 2; while (x<777) {x = x + 2;putchar(x)};x"
println("============ SRC CODE ============")
println(src)
println("==================================\n")

@ -520,7 +520,10 @@ class BaseParser(in: Scanner) extends Parser(in) {
val res = parseExpression
accept('}')
res
case _ => abort(s"Illegal start of simple expression")
case _ =>
println(in.peek)
println(in.peek1)
abort(s"Illegal start of simple expression")
}
def parseUAtom: Exp = if (in.hasNext(isOperator)) {
@ -579,7 +582,7 @@ class BaseParser(in: Scanner) extends Parser(in) {
val body = parseExpression
VarDec(name, tp, rhs, body).withPos(pos)
case Keyword("while") =>
val pos = accept("while").pos
val pos = in.next().pos
accept('(')
val cond = parseSimpleExpression
accept(')')
@ -648,7 +651,7 @@ class SyntacticSugarParser(in: Scanner) extends BaseParser(in) {
suf + "$" + next
}
override def parseSimpleExpression = in.peek match { // !!!
override def parseSimpleExpression = in.peek match {
case Keyword("if") =>
val pos = in.next().pos
accept('(')
@ -667,17 +670,11 @@ class SyntacticSugarParser(in: Scanner) extends BaseParser(in) {
override def parseExpression = {
// NOTE: parse expression terminates when it parse a simples expression.
// syntax sugar allows to have an other expression after it. !!!
var res = in.peek match {
case Keyword("val") | Keyword("var") | Keyword("while") =>
super.parseExpression
case _ =>
var simp = parseSimpleExpression
if(isNewLine(in.peek)) {
accept(';')
simp = Let(freshName(), UnknownType, simp, parseExpression).withPos(simp.pos)
}
simp
// syntax sugar allows to have an other expression after it.
var res = super.parseExpression
if(in.hasNext(_ match {case Delim(';') => true; case _ => false})){
accept(';')
res = Let(freshName(), UnknownType, res, parseExpression).withPos(res.pos)
}
res
}
@ -764,30 +761,24 @@ class FunctionParser(in: Scanner) extends SyntacticSugarParser(in) {
/*
* This function parse types.
*
* TODO !!!
* TODO
*/
override def parseType = in.peek match {
case Delim('(') =>
case Delim('(') =>
accept('(')
val list = parseList[Type](parseType, ',', tok => tok match {
case Delim(')') => false;
case _ => true
val list = parseList[Type](parseType, ',', _ match {
case Delim(')') => false; case _ => true
})
val argList = list map { tp => ("", tp)}
val args = list map { tp => ("", tp)}
accept("=>")
val rtp = parseType
FunType(argList, rtp)
FunType(args, parseType)
case _ =>
val typ = super.parseType
if(in.peek == Delim('=') && in.peek1 == Ident(">")) {
accept("=>")
val rtp = super.parseType
val typList: List[(String, Type)] = List(("", typ))
FunType(typList, rtp)
}
else {
typ
}
var ty = super.parseType
if(in.peek == Delim('=') && in.peek1 == Ident(">")) {
accept("=>")
ty = FunType(List(("", ty)), super.parseType)
}
ty
}
/*

@ -369,7 +369,7 @@ class SemanticAnalyzer(parser: Parser) extends Reporter with BugReporter {
*/
pt match {
case UnitType | IntType | BooleanType | CharType => VarAssign(x, rhsChecked).withType(rhsChecked.tp)
case _ => exp.withType(UnknownType)
case _ => exp.withType(UnitType)
}
case While(cond, lbody, body) =>
val condChecked = typeCheck(cond, BooleanType)(env)
@ -389,9 +389,9 @@ class SemanticAnalyzer(parser: Parser) extends Reporter with BugReporter {
case LetRec(funs, body) =>
// TODO modify to handle general case
val _env = env.withVals(funs.map {case FunDef(name, _, rtp, _) => (name, rtp)})
val funsChecked = funs map {case f@FunDef(_, _, rtp, _) => typeCheck(f, rtp)(_env) }
val bodyChecked = typeCheck(body, pt)( env.withVals(funsChecked map {case FunDef(name, _, rtp, _) => (name, rtp)}))
val _env = env.withVals(funs map {case FunDef(name, args, rtp, _) => (name, funType(args, rtp))})
val funsChecked = funs map {case f@FunDef(_, args, rtp, _) => typeCheck(f, funType(args, rtp))(_env) }
val bodyChecked = typeCheck(body, pt)( env.withVals(funsChecked map {case FunDef(name, args, rtp, _) => (name, funType(args, rtp))}))
LetRec(funsChecked, bodyChecked).withType(bodyChecked.tp)
case App(fun, args) =>

@ -38,4 +38,20 @@ class CompilerTest extends TimedSuite {
testCompiler(LetRec(Nil, Prim("-", List(Lit(10), Lit(2)))), 8)
}
test("extra_credit_fn_as_var") {
testCompiler(LetRec(Nil,Let("x",UnknownType,Ref("putchar"),Let("x$1",UnknownType,App(Ref("x"),List(Lit(97))),Lit(69)))), 69)
}
test("extra_credit_char_parse_toInt_toChar") {
testCompiler(LetRec(Nil,Let("x$1",UnitType,App(Ref("putchar"),List(App(Ref("toInt"),List(Lit('s'))))),Let("x$2",UnitType,App(Ref("putchar"),List(App(Ref("toInt"),List(Lit('s'))))),Let("x$3",UnitType,App(Ref("putchar"),List(App(Ref("toInt"),List(Lit('i'))))),Lit(96))))), 96)
testCompiler(LetRec(List(),App(Ref("toInt"),List(App(Ref("toChar"),List(Lit(420)))))), 164) // Int->Char narrow
}
test("func_decl_call") {
val pos = Position(0,0,0,0,0,0)
//def f(x:Int, y:Int, z:Char) = (x - y)*20 + 10 * toInt(z); f(6, 9, '0') == 420
testCompiler(LetRec(List(FunDef("f",List(Arg("x",IntType,pos), Arg("y",IntType,Position(0,0,0,0,0,0)), Arg("z",CharType,Position(0,0,0,0,0,0))),IntType,Prim("+",List(Prim("*",List(Prim("-",List(Ref("x"), Ref("y"))), Lit(20))), Prim("*",List(Lit(10), App(Ref("toInt"),List(Ref("z"))))))))),App(Ref("f"),List(Lit(6), Lit(9), Lit('0')))), 420)
//def f(x:Int) = 1 + x; val y = f(1); val z = f(2); y + z
testCompiler(LetRec(List(FunDef("f",List(Arg("x",IntType,pos)),IntType,Prim("+",List(Lit(1), Ref("x"))))),Let("y",IntType,App(Ref("f"),List(Lit(1))),Let("z",IntType,App(Ref("f"),List(Lit(2))),Prim("+",List(Ref("y"), Ref("z")))))), 5)
}
}

@ -17,4 +17,20 @@ class InterpretTest extends TimedSuite {
testInterpreter(Prim("-", List(Lit(10), Lit(2))), Cst(8))
}
// test("extra_credit_fn_as_var") {
// testInterpreter(LetRec(Nil,Let("x",UnknownType,Ref("putchar"),Let("x$1",UnknownType,App(Ref("x"),List(Lit(97))),Lit(69)))), Cst(69))
// }
// test("extra_credit_char_parse_toInt_toChar") {
// testInterpreter(LetRec(Nil,Let("x$1",UnitType,App(Ref("putchar"),List(App(Ref("toInt"),List(Lit('s'))))),Let("x$2",UnitType,App(Ref("putchar"),List(App(Ref("toInt"),List(Lit('s'))))),Let("x$3",UnitType,App(Ref("putchar"),List(App(Ref("toInt"),List(Lit('i'))))),Lit(96))))), Cst(96))
// testInterpreter(LetRec(List(),App(Ref("toInt"),List(App(Ref("toChar"),List(Lit(420)))))), Cst(164)) // Int->Char narrow
// }
// test("func_decl_call") {
// val pos = Position(0,0,0,0,0,0)
// //def f(x:Int, y:Int, z:Char) = (x - y)*20 + 10 * toInt(z); f(6, 9, '0') == 420
// testInterpreter(LetRec(List(FunDef("f",List(Arg("x",IntType,pos), Arg("y",IntType,Position(0,0,0,0,0,0)), Arg("z",CharType,Position(0,0,0,0,0,0))),IntType,Prim("+",List(Prim("*",List(Prim("-",List(Ref("x"), Ref("y"))), Lit(20))), Prim("*",List(Lit(10), App(Ref("toInt"),List(Ref("z"))))))))),App(Ref("f"),List(Lit(6), Lit(9), Lit('0')))), Cst(420))
// //def f(x:Int) = 1 + x; val y = f(1); val z = f(2); y + z
// testInterpreter(LetRec(List(FunDef("f",List(Arg("x",IntType,pos)),IntType,Prim("+",List(Lit(1), Ref("x"))))),Let("y",IntType,App(Ref("f"),List(Lit(1))),Let("z",IntType,App(Ref("f"),List(Lit(2))),Prim("+",List(Ref("y"), Ref("z")))))), Cst(5))
// }
}

@ -30,4 +30,5 @@ class ParserTest extends TimedSuite {
test("ParseOptionalType") {
testBaseParser("val x = 1; 2", Let("x", UnknownType, Lit(1), Lit(2)))
}
//see examples/hello.scala and pow.scala for more comprehensive tests
}

Loading…
Cancel
Save