Skip to content

Commit f24cb7e

Browse files
committed
Update to KtLox v1.1.0
1 parent ad2b046 commit f24cb7e

39 files changed

Lines changed: 327 additions & 250 deletions

README.md

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,22 +23,25 @@ https://github.com/munificent/craftinginterpreters
2323
- Inheritance and this/super keywords
2424
- Metaclasses(challenge from the book)
2525
- Traits(challenge from the book)
26+
- Framework for creating native functions/classes(since v1.1.0)
2627

2728
## Roadmap
2829

2930
### KtLox v1.1.0(current version)
3031
- Improved object model - Everything is an object, including nil, true, false, number, string, etc.
3132
- Framework for writing Native functions and classes.
32-
- root class Object which serves as superclass of every class.
33+
- Root class Object which serves as superclass of every class.
34+
- Remove print statement and replace it by print/println native functions.
3335

3436
### KtLox v1.2.0(next version)
3537
- Full Fledged Standard Library: Boolean, Number, String, Array, Dictionary, DateTime, etc.
3638
- Mechanism for efficiently loading standard library at interpreter startup.
37-
- (maybe) Split the Number class, which will distinguish between integers and floating numbers.
39+
- Split the Number class, which will distinguish between integers and floating numbers.
3840

3941
### KtLox v1.3.0
4042
- Syntactic Sugar for Array/Dictionary Literals.
41-
- Short closures/lambda expression.
43+
- Short closures/lambda expression with nonlocal returns.
44+
- Replace C style for loop by Kotlin style for-in loop for collection.
4245
- (maybe) Null-safe operator (?.).
4346

4447
### KtLox v1.4.0
@@ -50,6 +53,7 @@ https://github.com/munificent/craftinginterpreters
5053
- Refinement of metaclass system to match smalltalk's metaobject protocol.
5154
- Improvement of trait system in KtLox.
5255
- Add some Metaclasses and traits to the standard library.
56+
- (maybe) Add feature for anonymous class and trait.
5357

5458
### KtLox v1.6.0
5559
- Introduction of Namespace for KtLox's module system.
@@ -61,7 +65,7 @@ https://github.com/munificent/craftinginterpreters
6165
- Add class Exception as well as a few more exception subclasses to the standard library.
6266
- (maybe) Pattern Matching
6367

64-
### Ktlox v1.8.0
68+
### KtLox v1.8.0
6569
- Operator Overloading: enable user defined classes to overload operators, these operators are treated as method calls.
6670
- Method interception when an undefined method call is invoked on an object/class, similar to Smalltalk's doesNotUnderstand: message.
6771
- (maybe) Semicolon inference that allows semicolons to be omitted when its obvious that the statement is finished at the end of the line.
@@ -74,4 +78,4 @@ https://github.com/munificent/craftinginterpreters
7478
### KtLox v2.0.0
7579
- Optional static typing support for instance variables and function/method parameters.
7680
- (maybe) Type inference for immutable variables, as well as possible optimization for typed variables.
77-
- (maybe) Slot as refied variables, similar to Pharo Smalltalk and Self's implementation.
81+
- (maybe) Slot as reified variables, similar to Pharo Smalltalk and Self's implementation.

src/main/kotlin/Ast.kt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@ object Ast {
3838
"Function : Token name, Expr.Function functionBody",
3939
"Expression : Expr expression",
4040
"If : Expr condition, Stmt thenBranch, Stmt? elseBranch",
41-
"Print : Expr expression",
4241
"Return : Token keyword, Expr? value",
4342
"Trait : Token name, List<Expr.Variable> traits, List<Stmt.Function> methods",
4443
"Var : Token name, Expr? initializer",

src/main/kotlin/ast/Stmt.kt

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ abstract class Stmt {
1111
fun visitFunctionStmt(stmt: Function) : R
1212
fun visitExpressionStmt(stmt: Expression) : R
1313
fun visitIfStmt(stmt: If) : R
14-
fun visitPrintStmt(stmt: Print) : R
1514
fun visitReturnStmt(stmt: Return) : R
1615
fun visitTraitStmt(stmt: Trait) : R
1716
fun visitVarStmt(stmt: Var) : R
@@ -26,7 +25,7 @@ abstract class Stmt {
2625
override fun <R> accept(visitor: Visitor<R>) = visitor.visitBreakStmt(this)
2726
}
2827

29-
data class Class(val name: Token, val superclass: Expr.Variable, val traits: List<Expr.Variable>, val methods: List<Function>, val classMethods: List<Function>) : Stmt(){
28+
data class Class(val name: Token, val superclass: Expr.Variable, val traits: List<Expr.Variable>, val methods: List<Stmt.Function>, val classMethods: List<Stmt.Function>) : Stmt(){
3029
override fun <R> accept(visitor: Visitor<R>) = visitor.visitClassStmt(this)
3130
}
3231

@@ -42,15 +41,11 @@ abstract class Stmt {
4241
override fun <R> accept(visitor: Visitor<R>) = visitor.visitIfStmt(this)
4342
}
4443

45-
data class Print(val expression: Expr) : Stmt(){
46-
override fun <R> accept(visitor: Visitor<R>) = visitor.visitPrintStmt(this)
47-
}
48-
4944
data class Return(val keyword: Token, val value: Expr?) : Stmt(){
5045
override fun <R> accept(visitor: Visitor<R>) = visitor.visitReturnStmt(this)
5146
}
5247

53-
data class Trait(val name: Token, val traits: List<Expr.Variable>, val methods: List<Function>) : Stmt(){
48+
data class Trait(val name: Token, val traits: List<Expr.Variable>, val methods: List<Stmt.Function>) : Stmt(){
5449
override fun <R> accept(visitor: Visitor<R>) = visitor.visitTraitStmt(this)
5550
}
5651

src/main/kotlin/common/LoxClass.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ import com.mysidia.ktlox.interpreter.Interpreter
55
open class LoxClass(val name: String,
66
val superclass: LoxClass?,
77
val methods: MutableMap<String, LoxCallable>,
8-
metaclass: LoxClass?) : LoxObject(metaclass), LoxCallable{
8+
val traits: MutableList<LoxTrait>? = null,
9+
metaclass: LoxClass? = null) : LoxObject(metaclass), LoxCallable{
910

1011
private val initializer by lazy { findMethod("init") }
1112
override val arity get() = initializer?.arity ?: 0

src/main/kotlin/common/LoxClassClass.kt

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,24 @@ import com.mysidia.ktlox.interpreter.Interpreter
55
object LoxClassClass : LoxNativeClass("Class", LoxObjectClass, null) {
66

77
init{
8+
klass = this
89
defineNativeMethod("getSuperclass", 0, this::getSuperclassDef)
10+
defineNativeMethod("getTraits", 0, this::getTraitsDef)
911
defineNativeMethod("isClass", 0, this::isClassDef)
1012
defineNativeMethod("toString", 0, this::toStringDef)
1113
}
1214

1315
private fun getSuperclassDef(interpreter: Interpreter, arguments: List<Any?>?) = (interpreter.thisInstance as LoxClass).superclass
1416

17+
private fun getTraitsDef(interpreter: Interpreter, arguments: List<Any?>?) : String{
18+
val self = interpreter.thisInstance as LoxClass
19+
var traits = ""
20+
self.traits?.forEach { trait ->
21+
traits += "${trait.name} " + trait.printParents()
22+
}
23+
return traits
24+
}
25+
1526
private fun isClassDef(interpreter: Interpreter, arguments: List<Any?>?) = true
1627

1728
private fun toStringDef(interpreter: Interpreter, arguments: List<Any?>?) = interpreter.thisInstance.className

src/main/kotlin/common/LoxNativeClass.kt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,15 @@ import com.mysidia.ktlox.interpreter.Interpreter
44

55
abstract class LoxNativeClass(name: String,
66
superclass: LoxClass?,
7-
metaclass: LoxClass? = null) : LoxClass(name, superclass, mutableMapOf(), metaclass){
7+
traits: MutableList<LoxTrait>? = null,
8+
metaclass: LoxClass? = null) : LoxClass(name, superclass, mutableMapOf(), traits, metaclass){
89

910
fun defineNativeGetter(name: String, body: (interpreter : Interpreter, arguments: List<Any?>?) -> Any?){
1011
methods[name] = LoxNativeMethod(name, 0, true, null, body)
1112
}
1213

1314
fun defineNativeMetaclass(name: String, superclass: LoxClass? = LoxClassClass){
14-
klass = LoxClass(name, LoxClassClass, mutableMapOf(), null)
15+
klass = LoxClass(name, superclass, mutableMapOf(), null, LoxClassClass)
1516
}
1617

1718
fun defineNativeMethod(name: String, arity: Int, body: (interpreter : Interpreter, arguments: List<Any?>?) -> Any?){

src/main/kotlin/common/LoxNativeFunction.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@ import com.mysidia.ktlox.interpreter.Interpreter
44

55
abstract class LoxNativeFunction(protected val name: String,
66
override val arity: Int,
7-
protected val body: () -> Any?
7+
protected val body: (arguments: List<Any?>?) -> Any?
88
) : LoxObject(LoxFunctionClass), LoxCallable {
99

1010
override val isGetter = false
11-
override fun call(interpreter: Interpreter, arguments: List<Any?>?) = body.invoke()
11+
override fun call(interpreter: Interpreter, arguments: List<Any?>?) = body.invoke(arguments)
1212
override fun toString() = "<native fn: $name>"
1313
}

src/main/kotlin/common/LoxObjectClass.kt

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,16 @@ object LoxObjectClass : LoxNativeClass("Object", null){
88
defineNativeMetaclass("Object class")
99
defineNativeGetter("className", this::classNameProp)
1010
defineNativeMethod("getClass", 0, this::getClassDef)
11-
defineNativeMethod("getClassName", 0, this::getClassNameDef)
1211
defineNativeMethod("hashCode", 0, this::hashCodeDef)
12+
defineNativeMethod("hasTrait", 1, this::hasTraitDef)
1313
defineNativeMethod("instanceOf", 1, this::instanceOfDef)
1414
defineNativeMethod("isBoolean", 0, this::isBooleanDef)
1515
defineNativeMethod("isClass", 0, this::isClassDef)
1616
defineNativeMethod("isNil", 0, this::isNilDef)
1717
defineNativeMethod("isNilOrEmpty", 0, this::isNilOrEmptyDef)
1818
defineNativeMethod("isNumber", 0, this::isNumberDef)
1919
defineNativeMethod("isString", 0, this::isStringDef)
20+
defineNativeMethod("isTrait", 0, this::isTraitDef)
2021
defineNativeMethod("memberOf", 1, this::memberOfDef)
2122
defineNativeMethod("toString", 0, this::toStringDef)
2223
}
@@ -25,13 +26,20 @@ object LoxObjectClass : LoxNativeClass("Object", null){
2526

2627
private fun getClassDef(interpreter: Interpreter, arguments: List<Any?>?) = interpreter.thisInstance.klass
2728

28-
private fun getClassNameDef(interpreter: Interpreter, arguments: List<Any?>?) = interpreter.thisInstance.className
29-
3029
private fun hashCodeDef(interpreter: Interpreter, arguments: List<Any?>?) = interpreter.thisInstance.hashCode()
3130

31+
private fun hasTraitDef(interpreter: Interpreter, arguments: List<Any?>?) : Boolean{
32+
val self = interpreter.thisInstance
33+
val trait = arguments!![0] as? LoxTrait ?: return false
34+
self.klass?.traits?.forEach {
35+
if(it == trait || it.parents.contains(trait)) return true
36+
}
37+
return false
38+
}
39+
3240
private fun instanceOfDef(interpreter: Interpreter, arguments: List<Any?>?) : Boolean{
3341
val self = interpreter.thisInstance
34-
val klass = arguments!![0] as? LoxClass ?: return false
42+
val klass = arguments!![0] as? LoxClass ?: return hasTraitDef(interpreter, arguments)
3543
if(self.className == klass.name) return true
3644

3745
var superKlass = self.klass
@@ -54,6 +62,8 @@ object LoxObjectClass : LoxNativeClass("Object", null){
5462

5563
private fun isStringDef(interpreter: Interpreter, arguments: List<Any?>?) = false
5664

65+
private fun isTraitDef(interpreter: Interpreter, arguments: List<Any?>?) = false
66+
5767
private fun memberOfDef(interpreter: Interpreter, arguments: List<Any?>?) : Boolean{
5868
val self = interpreter.thisInstance
5969
val klass = arguments!![0] as? LoxClass ?: return false

src/main/kotlin/common/LoxTrait.kt

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,22 @@ package com.mysidia.ktlox.common
22

33
class LoxTrait(val name: String,
44
val methods: Map<String, LoxCallable>,
5-
val parents: List<LoxTrait>? = null) : LoxObject(LoxTraitClass) {
5+
val traits: List<LoxTrait>? = null) : LoxObject(LoxTraitClass) {
6+
7+
val parents : List<LoxTrait> by lazy {
8+
val parentTraits = mutableListOf<LoxTrait>()
9+
traits?.forEach {
10+
parentTraits.add(it)
11+
parentTraits.addAll(it.parents)
12+
}
13+
parentTraits
14+
}
15+
16+
fun printParents() : String{
17+
var parentTraits = ""
18+
parents.forEach { parentTraits += "${it.name} " }
19+
return parentTraits
20+
}
621

722
override fun toString() = name
823
}

src/main/kotlin/common/LoxTraitClass.kt

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,18 @@ object LoxTraitClass : LoxNativeClass("Trait", LoxObjectClass){
66

77
init{
88
defineNativeMetaclass("Trait class")
9-
defineNativeMethod("parents", 0, this::parentsDef)
9+
defineNativeMethod("getParentTraits", 0, this::getParentTraitsDef)
10+
defineNativeMethod("isTrait", 0, this::isTraitDef)
1011
}
1112

12-
private fun parentsDef(interpreter: Interpreter, arguments: List<Any?>?) : String{
13+
private fun getParentTraitsDef(interpreter: Interpreter, arguments: List<Any?>?) : String{
1314
val self = interpreter.thisInstance as LoxTrait
1415
var parents = ""
15-
self.parents?.forEach {
16-
parents += "${it.name} "
16+
self.traits?.forEach { trait ->
17+
parents += "${trait.name} " + trait.printParents()
1718
}
1819
return parents
1920
}
21+
22+
private fun isTraitDef(interpreter: Interpreter, arguments: List<Any?>?) = true
2023
}

0 commit comments

Comments
 (0)