Skip to content
This repository was archived by the owner on Feb 23, 2022. It is now read-only.

Commit 4f149c0

Browse files
committed
Finish Inheritence without Super
1 parent 1b093f0 commit 4f149c0

15 files changed

+89
-46
lines changed

Makefile

+1-3
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,11 @@ uit: classes manifest
1313

1414
classes: clean
1515
@echo "[x] Compiling Java."
16-
@bash -c 'JAVA_TOOL_OPTIONS=-Dfile.encoding=UTF8 javac -g:none -Werror -d "tmp" -cp "lib/*:src" src/com/heinthanth/uit/Main.java 2> >(grep -v "^Picked up JAVA_TOOL_OPTIONS:" >&2)'
16+
@bash -c 'JAVA_TOOL_OPTIONS=-Dfile.encoding=UTF8 javac -Werror -d "tmp" -cp "lib/*:src" src/com/heinthanth/uit/Main.java 2> >(grep -v "^Picked up JAVA_TOOL_OPTIONS:" >&2)'
1717

1818
node:
1919
@echo "[x] Generating Runtime Nodes."
20-
# create node generator
2120
@javac -d "tmp" src/com/heinthanth/uit/Utils/GenerateNode.java >/dev/null
22-
# Generate Expression and Statement nodes
2321
@java -cp "tmp" com.heinthanth.uit.Utils.GenerateNode src/com/heinthanth/uit/Runtime >/dev/null
2422

2523
manifest:

README.md

+9-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,15 @@
88

99
## Documentation
1010

11-
Since it's under development, documentations hasn't been written yet.
11+
Since it's under development, documentations hasn't been written yet. It's basically heavy modified version of Lox Lang ( `CraftingInterpreters` ).
12+
13+
## New Features
14+
15+
- [x] Static Data Types
16+
- [x] `Modulo`, `Exponent`, `Prefix`, `Postfix` operators
17+
- [x] Loop Control ( `Break`, `Continue` )
18+
- [x] OOP with Access Modifier (`Public`, `Private`, `Protected`)
19+
- [ ] `Super`
1220

1321
## Installation
1422

build/uit.jar

8.15 KB
Binary file not shown.

examples/class.uit

+10-8
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,18 @@
1-
class Dog
2-
private string name;
1+
class Animal
2+
protected string name = "Dog";
33

4-
public void __construct(string name)
5-
set this->name = name;
4+
protected void greet()
5+
output "Hello";
66
endfunc
7+
endclass
78

8-
public void greet()
9-
output "Hello, I'm " . this->name . "\n";
9+
class Dog extends Animal
10+
public void debug()
11+
output this->greet();
1012
endfunc
1113
endclass
1214

1315
start
14-
object bob = new Dog("Bob");
15-
bob->greet();
16+
object bob = new Dog();
17+
bob->debug();
1618
stop

grammar.txt

+4-2
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@ declaration -> classDeclaration
55
| variableDeclaration
66
| statement
77

8-
classDeclaration -> "class" IDENTIFIER memberDeclaration* "endclass"
8+
classDeclaration -> "class" IDENTIFIER "extends" IDENTIFIER
9+
memberDeclaration*
10+
"endclass"
911
memberDeclaration -> ( ( "public" | "private" | "protected" ) variableDeclaration )*
1012

1113
variableDeclaration -> ( "num" | "string" | "boolean" ) IDENTIFIER ( "=" expression )? ";"
@@ -69,7 +71,7 @@ call -> "new" primary "(" arguments* ")"
6971
primary -> literal | grouping | IDENTIFIER
7072

7173
grouping -> "(" expression ")"
72-
literal -> NUMBER | STRING | BOOLEAN
74+
literal -> NUMBER | STRING | BOOLEAN | "this"
7375
operator -> "==" | "!=" | ">" | ">=" | "<" | "<="
7476
| "+" | "-" | "*" | "/" | "%" | "^"
7577
| "."

src/com/heinthanth/uit/Interpreter/Environment.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ public class Environment {
1616
/**
1717
* nested loop တွေအတွက် parent variable
1818
*/
19-
private final Environment parent;
19+
public final Environment parent;
2020

2121
/**
2222
* assign parent environment

src/com/heinthanth/uit/Interpreter/Interpreter.java

+11-1
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,14 @@ public Void visitReturnStatement(Statement.ReturnStatement statement) {
9999

100100
@Override
101101
public Void visitClassStatement(Statement.ClassStatement statement) {
102+
Object superclass = null;
103+
if (statement.parent != null) {
104+
superclass = evaluate(statement.parent);
105+
if (!(superclass instanceof UitClass)) {
106+
throw new RuntimeError(statement.parent.identifier, "Parent must be a class.");
107+
}
108+
}
109+
102110
environment.define(statement.identifier, null);
103111

104112
Map<String, Token> accessModifier = new HashMap<>();
@@ -133,7 +141,9 @@ public Void visitClassStatement(Statement.ClassStatement statement) {
133141
accessModifier.put(method.getKey().identifier.lexeme, method.getValue());
134142
}
135143

136-
UitClass klass = new UitClass(statement.identifier.lexeme, props, methods, accessModifier);
144+
UitClass klass = new UitClass(statement.identifier.lexeme, (UitClass) superclass, props, methods,
145+
accessModifier);
146+
137147
environment.assign(statement.identifier, klass);
138148
return null;
139149
}

src/com/heinthanth/uit/Interpreter/Resolver.java

+4
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,10 @@ public Void visitClassStatement(ClassStatement statement) {
8080
declare(statement.identifier);
8181
define(statement.identifier);
8282

83+
if (statement.parent != null && statement.identifier.lexeme.equals(statement.parent.identifier.lexeme)) {
84+
errorHandler.reportError(statement.parent.identifier, "A class can't inherit from itself.");
85+
}
86+
8387
beginScope();
8488
scopes.peek().put("this", true);
8589

src/com/heinthanth/uit/Lexer/token_t.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ public enum token_t {
2828
// function
2929
FUNC, ENDFUNC, RETURN,
3030
// class
31-
CLASS, ENDCLASS, NEW, DART, PUBLIC, PRIVATE, PROTECTED, EXTENDS, THIS,
31+
CLASS, ENDCLASS, NEW, DART, PUBLIC, PRIVATE, PROTECTED, EXTENDS, THIS, SUPER,
3232
// other keywords
3333
SET, INPUT, OUTPUT,
3434
// other operator

src/com/heinthanth/uit/Parser/Parser.java

+9-5
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,6 @@
1010
import com.heinthanth.uit.Lexer.token_t;
1111
import com.heinthanth.uit.Runtime.Expression;
1212
import com.heinthanth.uit.Runtime.Statement;
13-
import com.heinthanth.uit.Runtime.Expression.ThisExpression;
14-
import com.heinthanth.uit.Runtime.Expression.VariableAccessExpression;
1513
import com.heinthanth.uit.Utils.ErrorHandler;
1614

1715
import static com.heinthanth.uit.Lexer.token_t.*;
@@ -107,6 +105,12 @@ private Statement classDeclaration() {
107105
Map<Statement.VariableDeclarationStatement, Token> properties = new HashMap<>();
108106
Map<Statement.FunctionStatement, Token> methods = new HashMap<>();
109107

108+
Expression.VariableAccessExpression parent = null;
109+
if (match(EXTENDS)) {
110+
expect(IDENTIFIER, "Expect superclass name.");
111+
parent = new Expression.VariableAccessExpression(previous());
112+
}
113+
110114
while (!check(ENDCLASS) && !isEOF()) {
111115
if (check(PUBLIC) || check(PRIVATE) || check(PROTECTED)) {
112116
Token access = advance();
@@ -121,7 +125,7 @@ private Statement classDeclaration() {
121125
}
122126
}
123127
expect(ENDCLASS, "Expect 'endclass' after class statement.");
124-
return new Statement.ClassStatement(identifier, properties, methods);
128+
return new Statement.ClassStatement(identifier, parent, properties, methods);
125129
}
126130

127131
/**
@@ -572,9 +576,9 @@ private Expression call() {
572576
expr = finishCall(expr);
573577
} else if (match(DART)) {
574578
Token name = expect(IDENTIFIER, "Expect member name after '->'.");
575-
if (expr instanceof VariableAccessExpression) {
579+
if (expr instanceof Expression.VariableAccessExpression) {
576580
expr = new Expression.GetExpression(expr, name, false);
577-
} else if (expr instanceof ThisExpression) {
581+
} else if (expr instanceof Expression.ThisExpression) {
578582
expr = new Expression.GetExpression(expr, name, true);
579583
}
580584
} else {

src/com/heinthanth/uit/Runtime/Statement.java

+3-1
Original file line numberDiff line numberDiff line change
@@ -177,11 +177,13 @@ public <R> R accept(Visitor<R> visitor) {
177177
public static class ClassStatement extends Statement {
178178

179179
public final Token identifier;
180+
public final Expression.VariableAccessExpression parent;
180181
public final Map<Statement.VariableDeclarationStatement,Token> properties;
181182
public final Map<Statement.FunctionStatement,Token> methods;
182183

183-
public ClassStatement(Token identifier, Map<Statement.VariableDeclarationStatement,Token> properties, Map<Statement.FunctionStatement,Token> methods) {
184+
public ClassStatement(Token identifier, Expression.VariableAccessExpression parent, Map<Statement.VariableDeclarationStatement,Token> properties, Map<Statement.FunctionStatement,Token> methods) {
184185
this.identifier = identifier;
186+
this.parent = parent;
185187
this.properties = properties;
186188
this.methods = methods;
187189
}

src/com/heinthanth/uit/Runtime/UitClass.java

+30-17
Original file line numberDiff line numberDiff line change
@@ -9,49 +9,58 @@
99
import com.heinthanth.uit.Utils.TypeMapper;
1010

1111
public class UitClass implements UitCallable {
12-
final String name;
13-
12+
public final String name;
13+
private final UitClass parent;
1414
private final Map<String, Token> accessModifier;
1515
private final Map<String, Object> properties;
1616
private final Map<String, UitFunction> methods;
1717

18-
public UitClass(String name, Map<String, Object> props, Map<String, UitFunction> methods,
18+
public UitClass(String name, UitClass parent, Map<String, Object> props, Map<String, UitFunction> methods,
1919
Map<String, Token> accessModifier) {
2020
this.name = name;
21+
this.parent = parent;
2122
this.properties = props;
2223
this.methods = methods;
2324
this.accessModifier = accessModifier;
2425
}
2526

26-
public Object findProp(Token member, boolean fromThis) {
27+
public Object findProp(Token member, boolean fromThis, boolean fromChild) {
2728
if (properties.containsKey(member.lexeme)) {
2829
Token am = accessModifier.get(member.lexeme);
29-
if (fromThis || am.type == token_t.PUBLIC) {
30+
if ((fromChild && (am.type == token_t.PUBLIC || am.type == token_t.PROTECTED))
31+
|| (!fromChild && (fromThis || am.type == token_t.PUBLIC))) {
3032
return properties.get(member.lexeme);
3133
} else {
32-
throw new RuntimeError(am, "Cannot access '" + am.lexeme + "' member outside of class.");
34+
throw new RuntimeError(am, "Cannot access '" + am.lexeme + "' member outside of '" + name + "' class.");
3335
}
3436
}
37+
if (parent != null) {
38+
return parent.findProp(member, fromThis, true);
39+
}
3540
return null;
36-
3741
}
3842

39-
public UitFunction findMethod(Token member, boolean fromThis) {
43+
public UitFunction findMethod(Token member, boolean fromThis, boolean fromChild) {
4044
if (methods.containsKey(member.lexeme)) {
4145
Token am = accessModifier.get(member.lexeme);
42-
if (fromThis || am.type == token_t.PUBLIC) {
46+
if ((fromChild && (am.type == token_t.PUBLIC || am.type == token_t.PROTECTED))
47+
|| (!fromChild && (fromThis || am.type == token_t.PUBLIC))) {
4348
return methods.get(member.lexeme);
4449
} else {
45-
throw new RuntimeError(am, "Cannot access '" + am.lexeme + "' member outside of class.");
50+
throw new RuntimeError(am, "Cannot access '" + am.lexeme + "' member outside of '" + name + "' class.");
4651
}
4752
}
53+
if (parent != null) {
54+
return parent.findMethod(member, fromThis, true);
55+
}
4856
return null;
4957
}
5058

51-
public void setProp(Token member, Object value, boolean fromThis) {
59+
public void setProp(Token member, Object value, boolean fromThis, boolean fromChild) {
5260
if (properties.containsKey(member.lexeme)) {
5361
Token am = accessModifier.get(member.lexeme);
54-
if (fromThis || am.type == token_t.PUBLIC) {
62+
if ((fromChild && (am.type == token_t.PUBLIC || am.type == token_t.PROTECTED))
63+
|| (!fromChild && (fromThis || am.type == token_t.PUBLIC))) {
5564
Object old = properties.get(member.lexeme);
5665
if (value.getClass() == old.getClass()) {
5766
properties.put(member.lexeme, value);
@@ -67,20 +76,24 @@ public void setProp(Token member, Object value, boolean fromThis) {
6776
throw new RuntimeError(member, msg.toString());
6877
}
6978
} else {
70-
throw new RuntimeError(am, "Cannot access '" + am.lexeme + "' member outside of class.");
79+
throw new RuntimeError(am, "Cannot access '" + am.lexeme + "' member outside of '" + name + "' class.");
7180
}
7281
} else if (methods.containsKey(member.lexeme)) {
7382
throw new RuntimeError(member, "Cannot re-assign method '" + member.lexeme + "'.");
7483
} else {
75-
throw new RuntimeError(member, "No member named '" + member.lexeme + "' in '" + name + "' class.");
84+
if (parent != null) {
85+
parent.setProp(member, value, fromThis, true);
86+
} else {
87+
throw new RuntimeError(member, "No member named '" + member.lexeme + "' in '" + name + "' class.");
88+
}
7689
}
7790
}
7891

7992
@Override
8093
public Object invoke(Interpreter interpreter, List<Object> arguments) {
8194
UitInstance instance = new UitInstance(this);
82-
UitFunction initializer = findMethod(new Token(token_t.IDENTIFIER, "__construct", -1, -1), true);
83-
if (initializer.declaration.type.type != token_t.FRT_VOID)
95+
UitFunction initializer = findMethod(new Token(token_t.IDENTIFIER, "__construct", -1, -1), true, false);
96+
if (initializer != null && initializer.declaration.type.type != token_t.FRT_VOID)
8497
throw new RuntimeError(initializer.declaration.type, "Object constructor must be void method.");
8598
if (initializer != null) {
8699
initializer.bind(instance).invoke(interpreter, arguments);
@@ -90,7 +103,7 @@ public Object invoke(Interpreter interpreter, List<Object> arguments) {
90103

91104
@Override
92105
public int argsCount() {
93-
UitFunction initializer = findMethod(new Token(token_t.IDENTIFIER, "__construct", -1, -1), true);
106+
UitFunction initializer = findMethod(new Token(token_t.IDENTIFIER, "__construct", -1, -1), true, false);
94107
if (initializer == null)
95108
return 0;
96109
return initializer.argsCount();

src/com/heinthanth/uit/Runtime/UitFunction.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ public Object invoke(Interpreter interpreter, List<Object> arguments) {
7676

7777
if (isInitializer)
7878
return closure.getAt(0, "this");
79-
return null;
79+
return "";
8080
}
8181

8282
@Override

src/com/heinthanth/uit/Runtime/UitInstance.java

+4-4
Original file line numberDiff line numberDiff line change
@@ -3,24 +3,24 @@
33
import com.heinthanth.uit.Lexer.Token;
44

55
public class UitInstance {
6-
private UitClass klass;
6+
public UitClass klass;
77

88
public UitInstance(UitClass klass) {
99
this.klass = klass;
1010
}
1111

1212
public Object get(Token name, boolean fromThis) {
13-
Object prop = klass.findProp(name, fromThis);
13+
Object prop = klass.findProp(name, fromThis, false);
1414
if (prop != null)
1515
return prop;
16-
UitFunction method = klass.findMethod(name, fromThis);
16+
UitFunction method = klass.findMethod(name, fromThis, false);
1717
if (method != null)
1818
return method.bind(this);
1919
throw new RuntimeError(name, "No member named '" + name.lexeme + "' in '" + klass.name + "' class.");
2020
}
2121

2222
public void set(Token name, Object value, boolean fromThis) {
23-
klass.setProp(name, value, fromThis);
23+
klass.setProp(name, value, fromThis, false);
2424
}
2525

2626
@Override

src/com/heinthanth/uit/Utils/GenerateNode.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ public static void main(String[] args) throws IOException {
4747
"ContinueStatement : ",
4848
"FunctionStatement : Token type, Token identifier, List<List<Token>> parameters, List<Statement> instructions",
4949
"ReturnStatement : Token ret, Expression value",
50-
"ClassStatement : Token identifier, Map<Statement.VariableDeclarationStatement,Token> properties, Map<Statement.FunctionStatement,Token> methods"
50+
"ClassStatement : Token identifier, Expression.VariableAccessExpression parent, Map<Statement.VariableDeclarationStatement,Token> properties, Map<Statement.FunctionStatement,Token> methods"
5151
),
5252
Arrays.asList(
5353
"java.util.List",

0 commit comments

Comments
 (0)