Skip to content

Commit

Permalink
Add isInstanceOf
Browse files Browse the repository at this point in the history
  • Loading branch information
vogon101 committed May 1, 2021
1 parent 2f01df7 commit 5e27a05
Show file tree
Hide file tree
Showing 12 changed files with 92 additions and 5 deletions.
3 changes: 3 additions & 0 deletions pyScaly_lib/ScalyObject.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,8 @@ def equals(self, obj):
return self.__eq__(obj)


def isInstanceOf(self, cls):
return isinstance(self, cls)


#TODO: isInstanceOf?
2 changes: 2 additions & 0 deletions src/main/scala/com/freddieposer/scaly/AST/ASTBuilder.scala
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,8 @@ object ASTBuilder {
Application(SelectExpr(buildExpr(lhs), op.value), args.map(buildExpr))
case Term.ApplyUnary(Name(op), arg) =>
Application(SelectExpr(buildExpr(arg), f"unary_$op"), Nil)
case Term.ApplyType(fun, targs) =>
ApplicationWithType(buildExpr(fun), targs.map(buildScalyType))
case Term.Tuple(args) => TupleExpr(args.map(buildExpr))
case Term.Block(stats) => Block(stats.map(buildStatement))
case Term.Select(lhs, name) => SelectExpr(buildExpr(lhs), name.value)
Expand Down
2 changes: 2 additions & 0 deletions src/main/scala/com/freddieposer/scaly/AST/ScalyExpr.scala
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ case class TupleExpr(elems: List[Expr]) extends Expr

case class Application(lhs: Expr, args: List[Expr]) extends Expr

case class ApplicationWithType(lhs: Expr, targs: List[AST_ScalyType]) extends Expr

case class Block(statements: List[Statement]) extends Expr

case class IDExpr(name: String) extends Expr
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,14 @@ class ISTCompiler(_filename: String) {
args.flatMap(arg => compileExpression(arg, ctx)) -->
(CALL_FUNCTION, args.length.toByte)

case IST_ApplicationWithType(lhs, targs, _) =>
compileExpression(lhs, ctx) -->
targs.map(targ => targ.globalName.map {
name => (LOAD_GLOBAL, ctx.name(name.toPy)).toBCL
}.getOrElse(throw new Error(s"Cannot use $targ as type argument"))
).flat -->
(CALL_FUNCTION, 1.toByte)

case literal: IST_Literal =>
BytecodeList((LOAD_CONST, ctx.const(literal.py)))

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,10 @@ case class IST_Application(lhs: IST_Expression, args: List[IST_Expression], typ:
override lazy val maxStack: Int = List(lhs.maxStack, args.map(_.maxStack).sum, 1).max
}

case class IST_ApplicationWithType(lhs: IST_Expression, targ: List[ScalyType], typ: ScalyType) extends IST_Expression {
override lazy val maxStack: Int = List(lhs.maxStack + 2, targ.length * 2, 1).max
}

case class IST_New(name: String, args: List[IST_Expression], typ: ScalyType) extends IST_Expression {
override lazy val maxStack: Int = List(1, args.map(_.maxStack).sum).max
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,9 @@ trait ISTExprTransformer {

case IST_Application(lhs, args, typ) =>
IST_Application(transformExpr(lhs), args.map(transformExpr), typ)
case IST_ApplicationWithType(lhs, targ, typ) =>
IST_ApplicationWithType(transformExpr(lhs), targ, typ)

case IST_New(name, args, typ) =>
IST_New(name, args.map(transformExpr), typ)
case IST_Select(lhs, rhs, typ) =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,19 @@ sealed case class TypeError(message: String,

override def toString: String = this match {
case context: TypeErrorContext =>
s"Error at ${context.node}\n${context.inner}"
s"Error $message \nat ${context.node}\n${context.inner}"
case failure: TypeErrorFromUnificationFailure =>
failure.toString
case _ =>
s"Type error at $node with $ctx"
s"Type error $message \nat $node\n with $ctx"
}

}

class TypeErrorContext(val inner: TypeError, override val node: ScalyAST)
(implicit override val ctx: TypeContext) extends TypeError(inner.message, node) {

override def toString: String = f"Error at $node with $ctx\n${inner.toString}"
override def toString: String = f"Error $message\nat $node\nwith $ctx\n${inner.toString}"

}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,8 @@ object TypeChecker {
typeCheck_Expr(lhs).flatMap { lhsExpr =>
lhsExpr.typ.getMember(rhs)
.map {
case l@Location(_: ScalyFunctionTypeWithTarg, _) =>
IST_Select(lhsExpr, rhs, l)
case l@Location(ScalyFunctionType(None, to), _) =>
IST_Application(IST_Select(lhsExpr, rhs, l), Nil, to)
case l => IST_Select(lhsExpr, rhs, l)
Expand All @@ -306,6 +308,8 @@ object TypeChecker {
ctx.getVarType(name)
.toRight(TypeError(s"Cannot find variable $name", expr))
.map {
case l@Location(_: ScalyFunctionTypeWithTarg, _) =>
IST_Name(name, l)
case l@Location(ScalyFunctionType(None, to), _) =>
IST_Application(IST_Name(name, l), Nil, to)
case l => IST_Name(name, l)
Expand All @@ -329,6 +333,10 @@ object TypeChecker {
case x => Right(x)
}
lhsTyp.flatMap {

case ScalyFunctionTypeWithTarg(None, to) =>
Right(IST_Application(lhsExpr, Nil, ScalyFunctionTypeWithTarg(None, to)))

case ScalyFunctionType(None, rType) =>
actuals match {
case Nil => Right(IST_Application(lhsExpr, Nil, rType))
Expand All @@ -340,6 +348,7 @@ object TypeChecker {
case ScalyFunctionType(Some(formalTypes), rType) =>
canApply(formalTypes, actuals, expr)
.map(exprs => IST_Application(lhsExpr, exprs, rType))

case obj =>
obj.getMember("apply") match {
case Right(Location(_: ScalyFunctionType, _)) => typeCheck_Expr(Application(SelectExpr(lhs, "apply"), actuals))
Expand All @@ -349,6 +358,18 @@ object TypeChecker {
}
}

case ApplicationWithType(lhs, targ :: Nil) =>
typeCheck_Expr(lhs).flatMap { lhsExpr =>
lhsExpr.typ match {
case ScalyFunctionTypeWithTarg(None, to) =>
targ.fromAST map { targType =>
IST_ApplicationWithType(lhsExpr, targType :: Nil, to)
}
case x => Left(TypeError(s"Only functions with one type argument and no parameters are supported, got $x", expr))
}

}

case IfExpr(cond, tBranch, fBranch) =>
typeCheck_Expr(cond)
.flatMap { condExpr =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package com.freddieposer.scaly.typechecker.types
import com.freddieposer.scaly.AST.ClassParam
import com.freddieposer.scaly.typechecker.context.TypeContext.{TypeMap, buildTypeMap}
import com.freddieposer.scaly.typechecker.types.ScalyType.defaultMembers
import com.freddieposer.scaly.typechecker.types.stdtypes.ScalyValType.ScalyNothingType
import com.freddieposer.scaly.typechecker.types.stdtypes.{ScalyAny, ScalyObject, ScalyValType}

case class ScalyFunctionType(from: Option[ScalyType], to: ScalyType) extends StaticScalyType {
Expand All @@ -25,6 +26,14 @@ object ScalyFunctionType {
}
}

class ScalyFunctionTypeWithTarg(f: Option[ScalyType], t: ScalyType) extends ScalyFunctionType(f, t)

object ScalyFunctionTypeWithTarg {
def unapply(arg: ScalyFunctionTypeWithTarg): Option[(Option[ScalyType], ScalyType)] = Some(arg.from, arg.to)

def apply(f: Option[ScalyType], t: ScalyType): ScalyFunctionTypeWithTarg = new ScalyFunctionTypeWithTarg(f, t)
}

class ScalyTupleType private(val elems: List[ScalyType]) extends StaticScalyType {

override lazy val parent: Option[ScalyType] = Some(ScalyObject)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ object ScalyObject extends StaticScalyType {

override protected lazy val memberTypes: TypeMap = buildTypeMap(Map(
"toString" -> (O --> ScalyStringType),
"equals" -> (ScalyObject --> ScalyBooleanType)
"equals" -> (ScalyObject --> ScalyBooleanType),
"isInstanceOf" -> (O -@-> ScalyBooleanType)
), SymbolSource.MEMBER)

override def toString: String = "ScalyObject"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
package com.freddieposer.scaly.typechecker.types.stdtypes

import com.freddieposer.scaly.typechecker.types.{ScalyFunctionType, ScalyTupleType, ScalyType}
import com.freddieposer.scaly.typechecker.types.{ScalyFunctionType, ScalyFunctionTypeWithTarg, ScalyTupleType, ScalyType}

object ScalyObjectUtils {

object O {
def -->(rhs: ScalyType): ScalyFunctionType =
ScalyFunctionType(None, rhs)
def -@-> (rhs: ScalyType): ScalyFunctionTypeWithTarg =
new ScalyFunctionTypeWithTarg(None, rhs)

}

implicit def ListToTypeTuple(ts: List[ScalyType]): ScalyType = ScalyTupleType(ts)
Expand All @@ -16,6 +19,9 @@ object ScalyObjectUtils {
def -->(rhs: ScalyType): ScalyFunctionType =
ScalyFunctionType(Some(lhs), rhs)

def -@-> (rhs: ScalyType): ScalyFunctionTypeWithTarg =
new ScalyFunctionTypeWithTarg(Some(lhs), rhs)

}

implicit class ExtendedList(ts: List[ScalyType]) {
Expand Down
28 changes: 28 additions & 0 deletions test_suite/compiler/features/S_isInstanceOf.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*
True
True
False
True
True
False
None
*/
object Main {

def main(): Unit = {

val foo = new Foo

print(this.isInstanceOf[Main])
print(this.isInstanceOf[Object])
print(this.isInstanceOf[Foo])
print(foo.isInstanceOf[Object])
print(foo.isInstanceOf[Foo])
print(foo.isInstanceOf[Main])

}

}

class Foo

0 comments on commit 5e27a05

Please sign in to comment.