Skip to content

Commit

Permalink
Merge pull request #292 from mcoblenz/yul-codegen
Browse files Browse the repository at this point in the history
add int256 type
  • Loading branch information
YinglanChen committed Jul 30, 2020
2 parents cf80281 + 9fbe7a1 commit 313f89f
Show file tree
Hide file tree
Showing 7 changed files with 54 additions and 15 deletions.
16 changes: 16 additions & 0 deletions src/main/scala/edu/cmu/cs/obsidian/codegen/CodeGen.scala
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,10 @@ class CodeGen (val target: Target, table: SymbolTable) {

private def marshallExprWithFullObjects(unmarshalledExpr: IJExpression, typ: ObsidianType): IJExpression = {
val marshalledArg = typ match {

case IntType() => unmarshalledExpr.invoke("toString");
case Int256Type() =>
throw new RuntimeException("int256 not supported in Fabric")
case BoolType() =>
val encoder = model.directClass("java.util.Base64").staticInvoke("getEncoder")
val bytes = JExpr.cond(unmarshalledExpr, JExpr.ref("TRUE_ARRAY"), JExpr.ref("FALSE_ARRAY"))
Expand All @@ -268,6 +271,8 @@ class CodeGen (val target: Target, table: SymbolTable) {
val newInt = JExpr._new(model.parseType("java.math.BigInteger"))
newInt.arg(stringRepresentation)
newInt
case Int256Type() =>
throw new RuntimeException("int256 not supported in Fabric")
case BoolType() =>
val ifLengthIncorrect = errorBlock._if(marshalledExpr.ref("length").eq(JExpr.lit(1)).not())
val exception = JExpr._new(model.directClass("edu.cmu.cs.obsidian.client.ChaincodeClientTransactionFailedException"))
Expand Down Expand Up @@ -321,6 +326,8 @@ class CodeGen (val target: Target, table: SymbolTable) {
exception.arg(intAsString)
test._then()._throw(exception)
decl
case Int256Type() =>
throw new RuntimeException("int256 not supported in Fabric")
case BoolType() =>
val ifLengthIncorrect = errorBlock._if(marshalledExpr.ref("length").eq(JExpr.lit(1)).not())
val exception = JExpr._new(model.directClass("edu.cmu.cs.obsidian.chaincode.BadArgumentException"))
Expand Down Expand Up @@ -1741,6 +1748,8 @@ class CodeGen (val target: Target, table: SymbolTable) {
val stringResult = returnObj.invoke("toString")
val charset = model.ref("java.nio.charset.StandardCharsets").staticRef("UTF_8")
stringResult.invoke("getBytes").arg(charset)
case Int256Type() =>
throw new RuntimeException("int256 not supported in Fabric")
case BoolType() => model.ref("edu.cmu.cs.obsidian.chaincode.ChaincodeUtils")
.staticInvoke("booleanToBytes").arg(returnObj)
case StringType() => val invocation = returnObj.invoke("getBytes")
Expand Down Expand Up @@ -2054,6 +2063,8 @@ class CodeGen (val target: Target, table: SymbolTable) {

nonNullBody.add(setInvocation)
}
case Int256Type() =>
throw new RuntimeException("int256 not supported in Fabric")
case BoolType() => {
val setterName: String = setterNameForField(field.name)
val setInvocation = JExpr.invoke(builderVar, setterName).arg(fieldVar)
Expand Down Expand Up @@ -2444,6 +2455,8 @@ class CodeGen (val target: Target, table: SymbolTable) {

ifNonempty._then().assign(fieldVar, newInteger)
}
case Int256Type() =>
throw new RuntimeException("int256 not supported in Fabric")
case BoolType() => {
val getterName = getterNameForField(javaFieldName)
// foo = archive.getFoo();
Expand Down Expand Up @@ -2653,6 +2666,7 @@ class CodeGen (val target: Target, table: SymbolTable) {
private def resolveType(typ: ObsidianType, table: SymbolTable, interfaceParam: Option[AbstractJType]): AbstractJType = {
typ match {
case IntType() => model.directClass("java.math.BigInteger")
case Int256Type() => throw new RuntimeException("int256 not supported in Fabric")
case BoolType() => model.BOOLEAN
case StringType() => model.ref("String")
case n: NonPrimitiveType => {
Expand Down Expand Up @@ -2769,6 +2783,8 @@ class CodeGen (val target: Target, table: SymbolTable) {
model.ref("java.math.BigInteger").staticInvoke("valueOf")
val _ = newInt.arg(0)
Some(newInt)
case Int256Type() =>
throw new RuntimeException("int256 not supported in Fabric")
case BoolType() =>
Some(JExpr.lit(false))
case StringType() =>
Expand Down
1 change: 1 addition & 0 deletions src/main/scala/edu/cmu/cs/obsidian/lexer/Lexer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ object Lexer extends RegexParsers {
case "owned" => OwnedT()
case "main" => MainT()
case "int" => IntT()
case "int256" => Int256T()
case "bool" => BoolT()
case "string" => StringT()
case "true" => TrueT()
Expand Down
1 change: 1 addition & 0 deletions src/main/scala/edu/cmu/cs/obsidian/lexer/Token.scala
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ case class CaseT() extends Token { override def toString: String = "case"}
case class OwnedT() extends Token { override def toString: String = "owned"}
case class MainT() extends Token { override def toString: String = "main"}
case class IntT() extends Token { override def toString: String = "int"}
case class Int256T() extends Token { override def toString: String = "int256"}
case class StringT() extends Token { override def toString: String = "string"}
case class BoolT() extends Token { override def toString: String = "bool"}
case class TrueT() extends Token { override def toString: String = "true"}
Expand Down
3 changes: 2 additions & 1 deletion src/main/scala/edu/cmu/cs/obsidian/parser/Parser.scala
Original file line number Diff line number Diff line change
Expand Up @@ -114,8 +114,9 @@ object Parser extends Parsers {
val intPrim = IntT() ^^ { t => IntType().setLoc(t) }
val boolPrim = BoolT() ^^ { t => BoolType().setLoc(t) }
val stringPrim = StringT() ^^ { t => StringType().setLoc(t) }
val int256Prim = Int256T() ^^ {t => Int256Type().setLoc(t)}

parseNonPrimitive | intPrim | boolPrim | stringPrim
parseNonPrimitive | intPrim | boolPrim | stringPrim | int256Prim
}

private def extractTypeFromPermission(permission: Option[~[Token, Seq[Identifier]]],
Expand Down
26 changes: 21 additions & 5 deletions src/main/scala/edu/cmu/cs/obsidian/typecheck/Checker.scala
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,8 @@ class Checker(globalTable: SymbolTable, verbose: Boolean = false) {
case (IntType(), IntType()) => true
case (BoolType(), BoolType()) => true
case (StringType(), StringType()) => true
case (Int256Type(), Int256Type()) => true
case (Int256Type(), IntType()) => true
case (np1: NonPrimitiveType, np2: NonPrimitiveType) =>
(np1, np2) match {
case (ContractReferenceType(c1, c1p, _), ContractReferenceType(c2, c2p, _)) =>
Expand Down Expand Up @@ -485,6 +487,7 @@ class Checker(globalTable: SymbolTable, verbose: Boolean = false) {
case (IntType(), IntType()) => Some(IntType())
case (BoolType(), BoolType()) => Some(BoolType())
case (StringType(), StringType()) => Some(StringType())
case (Int256Type(), Int256Type()) => Some(Int256Type())
case (np1: NonPrimitiveType, np2: NonPrimitiveType) =>
nonPrimitiveMergeTypes(np1, np2, contractTable).flatMap(s => Some(s))
case _ => None
Expand Down Expand Up @@ -590,15 +593,15 @@ class Checker(globalTable: SymbolTable, verbose: Boolean = false) {
// Eliminate things we can't invoke methods on first.
val nonPrimitiveReceiverType = receiverType match {
case BottomType() => return (BottomType(), contextAfterReceiver, false, receiverPrime, Nil, args)
case UnitType() | IntType() | BoolType() | StringType() =>
case UnitType() | IntType() | Int256Type() | BoolType() | StringType() =>
logError(e, NonInvokeableError(receiverType))
return (BottomType(), contextAfterReceiver, false, receiverPrime, Nil, args)
case np: NonPrimitiveType => np
}

//Finding out if the Contract is a FFIContract
val isFFIInvocation = receiverType match {
case BottomType() | UnitType() | IntType() | BoolType() | StringType() => false
case BottomType() | UnitType() | IntType() | Int256Type() | BoolType() | StringType() => false
case np : NonPrimitiveType =>
val contractTableOpt = context.contractTable.lookupContract(np.contractName)
contractTableOpt match {
Expand Down Expand Up @@ -708,7 +711,8 @@ class Checker(globalTable: SymbolTable, verbose: Boolean = false) {
(BottomType(), context, e)
}
}
case NumLiteral(_) => (IntType(), context, e)

case NumLiteral(_) => (Int256Type(), context, e)
case StringLiteral(_) => (StringType(), context, e)
case TrueLiteral() => (BoolType(), context, e)
case FalseLiteral() => (BoolType(), context, e)
Expand Down Expand Up @@ -764,6 +768,14 @@ class Checker(globalTable: SymbolTable, verbose: Boolean = false) {
// Regular BigInt addition
case (_: IntType | _: BottomType, _: IntType | _: BottomType) =>
(IntType(), c2, Add(e1Prime, e2Prime).setLoc(e))
// Int256 addition
case (_: Int256Type | _: BottomType, _: Int256Type | _: BottomType) =>
(Int256Type(), c2, Add(e1Prime, e2Prime).setLoc(e))
// Int256 + Int
case (_: Int256Type | _: BottomType, _: IntType | _: BottomType) =>
(IntType(), c2, Add(e1Prime, e2Prime).setLoc(e))
case (_: IntType | _: BottomType, _: Int256Type | _: BottomType) =>
(IntType(), c2, Add(e1Prime, e2Prime).setLoc(e))
// String concatenation
case (_: StringType | _: BottomType, _: StringType | _: BottomType) =>
(StringType(), c2, StringConcat(e1Prime, e2Prime).setLoc(e))
Expand Down Expand Up @@ -793,7 +805,9 @@ class Checker(globalTable: SymbolTable, verbose: Boolean = false) {
case Equals(e1: Expression, e2: Expression) =>
val (t1, c1, e1Prime) = inferAndCheckExpr(decl, context, e1, NoOwnershipConsumption())
val (t2, c2, e2Prime) = inferAndCheckExpr(decl, c1, e2, NoOwnershipConsumption())
if (t1 == t2) (BoolType(), c2, Equals(e1Prime, e2Prime).setLoc(e)) else {
if ((t1 == t2) || (t1 == Int256Type() && t2 == IntType()) || (t1 == IntType() && t2 == Int256Type())) {
(BoolType(), c2, Equals(e1Prime, e2Prime).setLoc(e))
} else {
if (!t1.isBottom && !t2.isBottom) {
logError(e, DifferentTypeError(e1, t1, e2, t2))
}
Expand All @@ -814,7 +828,9 @@ class Checker(globalTable: SymbolTable, verbose: Boolean = false) {
case NotEquals(e1: Expression, e2: Expression) =>
val (t1, c1, e1Prime) = inferAndCheckExpr(decl, context, e1, NoOwnershipConsumption())
val (t2, c2, e2Prime) = inferAndCheckExpr(decl, c1, e2, NoOwnershipConsumption())
if (t1 == t2) (BoolType(), c2, NotEquals(e1Prime, e2Prime).setLoc(e)) else {
if ((t1 == t2) || (t1 == Int256Type() && t2 == IntType()) || (t1 == IntType() && t2 == Int256Type())) {
(BoolType(), c2, NotEquals(e1Prime, e2Prime).setLoc(e))
} else {
if (!t1.isBottom && !t2.isBottom) {
logError(e, DifferentTypeError(e1, t1, e2, t2))
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -335,7 +335,7 @@ object ObsidianType {
}
}

/* int, bool, or string */
/* int, int256, unit, bool, or string */
sealed trait PrimitiveType extends ObsidianType {
val isBottom: Boolean = false
override def residualType(mode: OwnershipConsumptionMode): ObsidianType = this
Expand Down Expand Up @@ -409,6 +409,10 @@ case class StringType() extends PrimitiveType {
override def toString: String = "string"
}

case class Int256Type() extends PrimitiveType {
override def toString: String = "Int256"
}

case class UnitType() extends PrimitiveType {
override def toString: String = "unit"
}
Expand Down
16 changes: 8 additions & 8 deletions src/test/scala/edu/cmu/cs/obsidian/tests/TypeCheckerTests.scala
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ class TypeCheckerTests extends JUnitSuite {

@Test def operationTest(): Unit = {
runTest("resources/tests/type_checker_tests/SimpleOperations.obs",
(PlusTypeError(IntType(), BoolType()), 8)
(PlusTypeError(Int256Type(), BoolType()), 8)
::
(SubtypingError(
StringType(),
Expand All @@ -83,11 +83,11 @@ class TypeCheckerTests extends JUnitSuite {
BoolType(), false), 14)
::
(SubtypingError(
IntType(),
Int256Type(),
BoolType(), false), 16)
::
(SubtypingError(
IntType(),
Int256Type(),
BoolType(), false), 16)
::
Nil
Expand Down Expand Up @@ -171,7 +171,7 @@ class TypeCheckerTests extends JUnitSuite {
::
(MustReturnError("t_ret_nonprimitive"), 31)
::
(SubtypingError(IntType(),
(SubtypingError(Int256Type(),
ContractReferenceType(ContractType("C_Owned", Nil), Owned(), NotRemoteReferenceType()), false), 33)
::
(MustReturnError("no_return"), 38)
Expand Down Expand Up @@ -200,11 +200,11 @@ class TypeCheckerTests extends JUnitSuite {
TrueLiteral(),
BoolType(),
NumLiteral(5),
IntType()), 14)
Int256Type()), 14)
::
(DifferentTypeError(
NumLiteral(1),
IntType(),
Int256Type(),
FalseLiteral(),
BoolType()), 16)
::
Expand All @@ -226,7 +226,7 @@ class TypeCheckerTests extends JUnitSuite {
ContractReferenceType(ContractType("Invocation", Nil), Unowned(), NotRemoteReferenceType()),
"otherMethod"), 23)
::
(NonInvokeableError(IntType()), 25)
(NonInvokeableError(Int256Type()), 25)
::
(MethodUndefinedError(
ContractReferenceType(ContractType("OtherContract", Nil), Owned(), NotRemoteReferenceType()),
Expand Down Expand Up @@ -672,7 +672,7 @@ class TypeCheckerTests extends JUnitSuite {

@Test def revertTest(): Unit = {
runTest("resources/tests/type_checker_tests/Revert.obs",
(SubtypingError(IntType(), StringType(), false), 12) :: Nil)
(SubtypingError(Int256Type(), StringType(), false), 12) :: Nil)
}

@Test def inStateTest(): Unit = {
Expand Down

0 comments on commit 313f89f

Please sign in to comment.