From ce1c2de044c91624370411e23acab13b0381949b Mon Sep 17 00:00:00 2001 From: mikebarnett Date: Wed, 15 Jul 2009 21:03:41 +0000 Subject: Initial set of files. --- Chalice/src/ChaliceToCSharp.scala | 211 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 211 insertions(+) create mode 100644 Chalice/src/ChaliceToCSharp.scala (limited to 'Chalice/src/ChaliceToCSharp.scala') diff --git a/Chalice/src/ChaliceToCSharp.scala b/Chalice/src/ChaliceToCSharp.scala new file mode 100644 index 00000000..75135e38 --- /dev/null +++ b/Chalice/src/ChaliceToCSharp.scala @@ -0,0 +1,211 @@ +//----------------------------------------------------------------------------- +// +// Copyright (C) Microsoft Corporation. All Rights Reserved. +// +//----------------------------------------------------------------------------- +class ChaliceToCSharp { + + def convertProgram(classes: List[Class]): String = { + "using Chalice;" + nl + nl + + rep(classes map convertClass) + } + + def convertClass(cl: Class): String = if (cl.IsExternal) "" else { + "public class " + cl.id + " {" + nl + + indentMore { indent + "public " + cl.id + "() " + "{" + nl + indent + "}" } + nl + nl + + (if(0 < cl.Fields.length) { + indentMore { indent + "public " + cl.id + "(" + repsep(cl.Fields map { f => convertType(f.typ) + " " + f.Id }, ", ") + ") " + "{" + nl + + indentMore { rep(cl.Fields map { f => indent + "this." + f.Id + " = " + f.Id + ";" + nl}) } + + indent + "}" } + nl + nl + } else "") + + indentMore { repsep(cl.members map convertMember, nl) } + + "}" + nl + nl + } + + def convertMember(member: Member): String = { + member match { + case Field(id, tp) => + indent + "public " + convertType(tp) + " " + id + ";" + nl + case meth@Method(id, ins, outs, spec, body) => + var csharpmain = if(id.equals("Start") && ins.length == 0 && outs.length == 0) { + indent + "public static void Main() { " + nl + + indentMore { + indent + meth.Parent.id + " newObject = new " + meth.Parent.id + "();" + nl + + indent + "newObject.Start();" + nl + } + + indent + "}" + nl + nl + } else { "" }; + var params = repsep(ins map { variable => convertType(variable.t) + " " + variable.id }, ", ") + (if(ins.length > 0 && outs.length > 0) ", " else "") + + repsep(outs map { variable => "out " + convertType(variable.t) + " " + variable.id }, ", "); + csharpmain + + indent + "public " + "void " + id + "(" + params + ") " + "{" + nl + + indentMore { + rep(outs map { x => indent + x.id + " = " + defaultValue(x.t) + ";" + nl } ) + + rep(body map convertStatement) + } + + indent + "}" + nl + nl + + indent + "public delegate " + "void " + id + "_delegate" + "(" + params + ");" + nl + nl + + indent + "public class " + "Token_" + id + " { " + nl + + (indentMore { + indent + "public " + id + "_delegate " + "del;" + nl + + indent + "public " + "System.IAsyncResult " + "async;" + nl + + (rep(outs map { o: Variable => indent + "public " + convertType(o.t) + " " + o.id + ";" + nl })) + }) + + indent + "}" + nl + case Function(id, ins, out, spec, definition) => + indent + "public " + convertType(out) + " " + id + "(" + + repsep(ins map { variable => convertType(variable.t) + " " + variable.id }, ", ") + + ") " + "{" + nl + + indentMore { indent + "return " + convertExpression(definition) + ";" + nl } + + indent + "}" + nl + case MonitorInvariant(_) => indent + "// monitor invariant" + nl + case Predicate(_, _) => indent + "//predicate" + nl + } + } + + def convertStatement(statement: Statement): String = { + statement match { + case Assert(e) => indent + "// assert" + nl + case Assume(e) => indent + "assert " + convertExpression(e) + ";" // todo: what if e contains old, result, ... + case BlockStmt(ss) => indent + "{" + nl + (indentMore { rep(ss map convertStatement) }) + indent + "}" + nl + case IfStmt(guard, thn, els) => indent + "if (" + convertExpression(guard) + ")" + nl + convertStatement(thn) + + (if(els.isDefined) (indent + "else" + nl + convertStatement(els.get)) else { "" }) + nl + case LocalVar(id, tp, const, ghost, rhs) => + indent + convertType(tp) + " " + id + " = " + + (if(rhs.isDefined) convertExpression(rhs.get) else defaultValue(tp)) + + ";" + nl + case FieldUpdate(MemberAccess(target, f), rhs) => + indent + convertExpression(target) + "." + f + " = " + convertExpression(rhs) + ";" + nl + case Assign(VariableExpr(x), rhs) => + indent + x + " = " + convertExpression(rhs) + ";" + nl + case WhileStmt(guard, _, _, body) => + indent + "while (" + convertExpression(guard) + ")" + nl + convertStatement(body) + nl + case Call(lhs, target, id, args) => + indent + convertExpression(target) + "." + id + "(" + + repsep(args map convertExpression, ", ") + + (if(args.length > 0 && lhs.length > 0) ", " else "") + + repsep(lhs map { l => "out " + convertExpression(l) }, ", ") + + ")" + ";" + nl + case Install(_, _, _) => indent + "// install" + nl + case Share(_, _, _) => indent + "// share" + nl + case Unshare(_) => indent + "// unshare" + nl + case Downgrade(_) => indent + "// downgrade" + nl + case Acquire(obj) => indent + "System.Threading.Monitor.Enter(" + convertExpression(obj) + ")" + ";" + nl + case Release(obj) => indent + "System.Threading.Monitor.Exit(" + convertExpression(obj) + ")" + ";" + nl + case Lock(obj, body, false) => indent + "lock(" + convertExpression(obj) + ") " + nl + convertStatement(body) + nl + case Free(_) => indent + "// free" + nl + case Fold(_) => indent + "// fold" + nl + case Unfold(_) => indent + "// unfold" + nl + case RdAcquire(obj) => assert(false); "" + case RdRelease(obj) => assert(false); "" + case Lock(_, _, true) => assert(false); "" + case ca@CallAsync(declaresLocal, lhs, obj, id, args) => + val tokenName = if(declaresLocal) lhs.id else { uniqueInt += 1; "tok_" + uniqueInt }; + val call = convertExpression(obj) + "." + id; + val tokenClass = ca.m.Parent.id + ".Token_" + id; + val delegateName = ca.m.Parent.id + "." + id + "_delegate"; + indent + tokenClass + " " + tokenName + " = new " + tokenClass + "();" + nl + + indent + tokenName + "." + "del" + " = new " + delegateName + "(" + call + ");" + nl + + indent + tokenName + "." + "async" + " = " + tokenName + "." + "del" + "." + "BeginInvoke(" + repsep(args map convertExpression, ", ") + + (if(args.length > 0 && ca.m.outs.length > 0) ", " else "") + repsep(ca.m.outs map { o => "out " + tokenName + "." + o.id }, ", ") + + (if(args.length > 0 || ca.m.outs.length > 0) ", " else "") + "null, null" + + ");" + nl + case ja@JoinAsync(lhs, token) => + indent + convertExpression(token) + "." + "del.EndInvoke(" + + repsep(lhs map { x => "out " + x.id}, ", ") + + (if(lhs.length > 0) ", " else "") + convertExpression(token) + "." + "async" + ");" + nl + } + } + + def convertExpression(expression: RValue): String = { + expression match { + case IntLiteral(n) => "" + n + case BoolLiteral(b) => "" + b + case NullLiteral() => "null" + case th: ThisExpr => "this" + case VariableExpr(id) => id + case MemberAccess(target, f) => convertExpression(target) + "." + f + case newrhs@NewRhs(c, initialization) => + if(initialization.length == 0) { "new " + c + "()" } else { + val init = repsep(newrhs.typ.Fields map { f => (initialization.find { i => i.f == f}) match { + case None => defaultValue(f.typ) + case Some(init) => convertExpression(init.e); + } + }, ", "); + "new " + c + "(" + init + ")"; + } + case At(s, i) => convertExpression(s) + ".At(" + convertExpression(i) + ")" + case Append(s1, s2) => convertExpression(s1) + ".Append(" + convertExpression(s2) + ")" + case Take(s, i) => convertExpression(s) + ".Take(" + convertExpression(i) + ")" + case Drop(s, i) => convertExpression(s) + ".Drop(" + convertExpression(i) + ")" + case bin: BinaryExpr => "(" + convertExpression(bin.E0) + " " + bin.OpName + " " + convertExpression(bin.E1) + ")"// todo: <==> and ==> + case Unfolding(p, e) => convertExpression(e) + case FunctionApplication(target, id, args) => convertExpression(target) + "." + id + "(" + repsep(args map convertExpression, ", ") + ")" + case Not(e) => "(! " + convertExpression(e) + ")" + case EmptySeq(tp) => "new Chalice.ImmutableList<" + convertType(tp) + ">()" + case es@ExplicitSeq(elems) => + val elemType = new Type(es.typ.asInstanceOf[SeqClass].parameter); + "new Chalice.ImmutableList<" + convertType(elemType) + ">(" + + "new " + convertType(elemType) + "[] {" + repsep(elems map convertExpression, ", ") + "}" + + ")" + case Range(min, max) => "Chalice.ImmutableList.Range(" + convertExpression(min) + ", " + convertExpression(max) + ")" + case Length(s) => convertExpression(s) + ".Length" + case IfThenElse(c, thn, els) => "(" + convertExpression(c) + " ? " + convertExpression(thn) + " : " + convertExpression(els) + ")" + } + } + + def convertType(tp: Type): String = { + tp.typ match { + case t: TokenClass => t.c.FullName + ".Token_" + t.m + case s: SeqClass => "Chalice.ImmutableList<" + convertType(new Type(s.parameter)) + ">" + case IntClass => "int" + case BoolClass => "bool" + case NullClass => "object" + case Class(id, _, _, _) => id + } + } + + def defaultValue(tp: Type) = { + tp.typ match { + case t: TokenClass => "null" + case s: SeqClass => "new Chalice.ImmutableList<" + convertType(new Type(s.parameter)) + ">()" + case IntClass => "0" + case BoolClass => "false" + case NullClass => "null" + case Class(id, _, _, _) => "null" + } + } + + // utility methods below + + var uniqueInt: int = 0; + val nl = System.getProperty("line.separator"); + var indentLevel = 0 + + def rep(strings: List[String]): String = { + strings.foldLeft("")({ (a, b) => a + b }) + } + + def repsep(strings: List[String], separator: String): String = { + if(strings.length == 0) { + "" + } else { + strings.reduceLeft({ (a, b) => a + separator + b }) + } + } + + def indent: String = { + def doIndent(i: int): String = { + if(i==0) { "" } else { " " + doIndent(i-1) } + } + doIndent(indentLevel); + } + + def indentMore(what: => String) = { + val prev = indentLevel + indentLevel = indentLevel + 1 + val result = what + indentLevel = prev + result + } +} -- cgit v1.2.3