Homework 3
This commit is contained in:
parent
bf60a078d7
commit
0afc86ceeb
129 changed files with 3163 additions and 4316 deletions
|
|
@ -2,9 +2,10 @@
|
|||
<classpath>
|
||||
<classpathentry kind="src" path="src"/>
|
||||
<classpathentry kind="src" path="test"/>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
|
||||
<classpathentry kind="lib" path="lib/antlr-4.4-complete.jar"/>
|
||||
<classpathentry kind="lib" path="lib/junit-4.12.jar"/>
|
||||
<classpathentry kind="lib" path="lib/hamcrest-core-1.3.jar"/>
|
||||
<classpathentry kind="lib" path="lib/antlr-4.7.1-complete.jar"/>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
|
||||
<classpathentry kind="lib" path="lib/javaliParserObf.jar"/>
|
||||
<classpathentry kind="output" path="bin"/>
|
||||
</classpath>
|
||||
|
|
|
|||
2
.project
2
.project
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>Javali-HW2</name>
|
||||
<name>Javali-HW3</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
|
|
|
|||
|
|
@ -1,13 +0,0 @@
|
|||
antlr4.antlrRegisteredTools=4.4@/tmp/antlr-4.4-complete.jar\:4.7.1@/home/carlos/eth/cd/nop90/HW2/lib/antlr-4.7.1-complete.jar
|
||||
antlr4.antlrToolPath=/home/carlos/eth/cd/nop90/HW2/lib/antlr-4.7.1-complete.jar
|
||||
antlr4.encoding=UTF-8
|
||||
antlr4.listener=true
|
||||
antlr4.visitor=false
|
||||
antlr4.vmArgs=
|
||||
antlr4ide.is_project_specific=true
|
||||
autobuilding=true
|
||||
eclipse.preferences.version=1
|
||||
is_project_specific=
|
||||
outlet.DEFAULT_OUTPUT.cleanupDerived=true
|
||||
outlet.DEFAULT_OUTPUT.derived=true
|
||||
outlet.DEFAULT_OUTPUT.directory=./target/generated-sources/antlr4
|
||||
|
|
@ -1,7 +0,0 @@
|
|||
eclipse.preferences.version=1
|
||||
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
|
||||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
|
||||
org.eclipse.jdt.core.compiler.compliance=1.8
|
||||
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
|
||||
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
|
||||
org.eclipse.jdt.core.compiler.source=1.8
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
Grade: 29/30
|
||||
Grade: 25/25
|
||||
|
||||
251/251 tests passed [25/25]
|
||||
105/105 tests passed [20/20]
|
||||
|
||||
Submitted test cases: [5/5]
|
||||
|
||||
Submitted test cases: [4/5]
|
||||
55
README.md
Normal file
55
README.md
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
# Compiler design
|
||||
## Parser and syntactic analysis
|
||||
See repo containing [Homework #2](https://svn.inf.ethz.ch/svn/trg/cd_students/ss18/teams/nop90/HW2).
|
||||
|
||||
## Semantic analysis
|
||||
This project checks a list class declaration as trees of Ast nodes for
|
||||
possible semantic errors.
|
||||
|
||||
### Design
|
||||
The semantic checks described [here](./SemanticChecks.md) are implemented in three
|
||||
phases.
|
||||
|
||||
1. Circular inheritance check (just with the names, and checking for non-existent
|
||||
types) to avoid stack overflow problems in the main analysis. May throw a
|
||||
`NO_SUCH_TYPE` error if the parent of a given class doesn't exist.
|
||||
2. Main semantic analysis, performed by `StmtAnalyzer` and `ExprAnalyzer`,
|
||||
two visitors that traverse each `ClassDecl` and all of its contents looking
|
||||
for semantic errors. Some types and methods may not have been discovered
|
||||
when they are accessed, and to that end the functions `findType(String)`
|
||||
and `findMethod(String,ClassSymbol)` lookup both, searching unvisited class
|
||||
and method declarations in order to find the corresponding symbol.
|
||||
3. Lookup of start point (method `void main()` in `Main` class)
|
||||
|
||||
### Testing
|
||||
A set of test cases (Javali programs, valid and invalid) are provided. The ones
|
||||
designed specifically for this homework assignment are located in
|
||||
`javali_tests/HW3_nop90`, and they cover all the code in the `cd.frontend.semantic`
|
||||
and `cd.ir` packages. They cover all the kinds of errors that can arise
|
||||
from a semantic analysis of Javali programs. As the order of the errors
|
||||
is not determined, each test case only checks one failing condition, and
|
||||
therefore many more test cases are needed for this homework than for
|
||||
previous ones.
|
||||
|
||||
The test files are organized in folders, with names ending in Tests or Errors,
|
||||
the latter only contain test cases that result in semantic errors.
|
||||
|
||||
To run the tests that exist in the `javali_tests` folder you can simply run
|
||||
|
||||
$ ant clean clean-test compile test
|
||||
|
||||
### Development environment
|
||||
This project is designed for Eclipse and GNU/Linux, but it can be run
|
||||
in other environments, as long as they have a 32bit `IA 86x assembly` compiler
|
||||
and a `JVM`. Check the `Config` class for more information.
|
||||
|
||||
### Documentation
|
||||
Available as [javadoc](javadoc/index.html). It is generated running the following command:
|
||||
|
||||
$ ant clean-doc generate-doc
|
||||
|
||||
### Important files
|
||||
* `TODO.md`: contains tasks to complete
|
||||
* `SemanticChecks.md`: contains the semantic checks numbered for quick reference
|
||||
* [Javali Grammar](https://www.ethz.ch/content/dam/ethz/special-interest/infk/inst-cs/lst-dam/documents/Education/Classes/Spring2018/210_Compiler_Design/Homework/javali.pdf)
|
||||
* [HW3 statement](https://www.ethz.ch/content/dam/ethz/special-interest/infk/inst-cs/lst-dam/documents/Education/Classes/Spring2018/210_Compiler_Design/Homework/hw3.pdf)
|
||||
43
SemanticChecks.md
Normal file
43
SemanticChecks.md
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
# Class and method declaration errors
|
||||
1. All programs must have a method main() with void return type in the class Main (`INVALID_START_POINT`)
|
||||
2. The superclass of each class exists (`NO_SUCH_TYPE`)
|
||||
3. There is no circular inheritance (`CIRCULAR_INHERITANCE`)
|
||||
4. No class is declared with the name `Object` (`OBJECT_CLASS_DEFINED`)
|
||||
5. Unique names (`DOUBLE_DECLARATION`) for each group:
|
||||
1. Class names
|
||||
2. Field names in a single class (field shadowing is allowed)
|
||||
3. Method names in a single class (Override is allowed, overloading not)
|
||||
4. Method parameters and local variable names
|
||||
6. Overridden methods must: (`INVALID_OVERRIDE`)
|
||||
1. Have the same number of parameters
|
||||
2. The return types must match
|
||||
3. The type of the parameters must match (name can differ)
|
||||
|
||||
# Method body errors
|
||||
1. `write()` must take one argument of type `int` (`TYPE_ERROR`)
|
||||
2. `read()` and `writeln()` must take no arguments (`WRONG_NUMBER_OF_ARGUMENTS`)
|
||||
3. The condition of a `while` or `if` statement must be typed `booelan` (`TYPE_ERROR`)
|
||||
4. Assignments: the type of the right-hand side must be a suptype of the type of the left-hand side. (`TYPE_ERROR`)
|
||||
5. Operators (`TYPE_ERROR`):
|
||||
1. `*`, `/`, `%`, `+`, `-`, `<`, `>`, `<=`, `>=` take `int` arguments only.
|
||||
2. `!`, `&&`, `||` take `boolean` arguments only.
|
||||
3. `==` and `!=` takes any couple of arguments as long as one of the types is a subtype of the other.
|
||||
4. A cast is only possible if one of the types is a subtype of the other
|
||||
6. Method invocation, must match with declaration:
|
||||
1. The number of parameters (`WRONG_NUMBER_OF_ARGUMENTS`)
|
||||
2. The type of each of the parameters (`TYPE_ERROR`)
|
||||
7. Arrays:
|
||||
1. When indexing, the index expression must be an `int` (`TYPE_ERROR`)
|
||||
2. When creating one, the index expression must be an `int` (`TYPE_ERROR`)
|
||||
8. The constant `null` can be assigned to any reference type.
|
||||
9. The type name in a `new` statement must exist (`NO_SUCH_TYPE`)
|
||||
10. The left-hand side of an assignment can only be: (`NOT_ASSIGNABLE`)
|
||||
1. A variable
|
||||
2. A field
|
||||
3. Array dereferences (indexing)
|
||||
11. There must be no attempt to access the field or method of a
|
||||
non-object type, such as arrays or primitive types (`TYPE_ERROR`)
|
||||
12. A method with a return type must have a return statement at the end
|
||||
of all its paths (`MISSING_RETURN`). A while loop is not a valid return
|
||||
regardless of the condition. A ifElse must have a return on both the
|
||||
else and otherwise block. There may be some statements after a return.
|
||||
75
TODO.md
Normal file
75
TODO.md
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
## Possible code changes
|
||||
### General
|
||||
* DONE Use more specific messages when throwing a `SemanticFailure` exception. This has the caveat that the automated testing relies on those tests?
|
||||
|
||||
### StmtAnalyzer
|
||||
* DONE Propagate the change of class parameter from `ExprAnalyzer`.
|
||||
* DONE Complete checks for `MISSING_RETURN`, some ideas:
|
||||
* DONE Assume no instructions will appear after a return statement and analyze only the last `Stmt` using other visitor
|
||||
with different class parameters (for example passing the desired type and returning a `Optional<TypeSymbol>`).
|
||||
* DONE Decide the logic behind a return statement in a `while` loop, maybe treat it as an `if` with an empty `else` block.
|
||||
* A `while` as last instruction is not a valid return.
|
||||
* A `if` as last instruction must have a valid return a the end of its then and otherwise blocks.
|
||||
|
||||
### ExprAnalyzer
|
||||
* DONE Change the second class parameter to give method AND class information (needed by var and this nodes)
|
||||
* DISCARDED Add a ClassSymbol to MethodSymbol and use it as class parameter, the problem arises when visiting a method,
|
||||
should an empty method with the proper class be provided? Could also be solved by using `Symbol` as class parameter.
|
||||
* DONE Create a new class that includes a `ClassSymbol` and a `MethodSymbol` and use that. Keep `MethodSymbol == null`
|
||||
when appropriate.
|
||||
|
||||
## Tests
|
||||
This tests have been selected to increase to 100% the code coverage obtained by running the tests designed for the previous HW,
|
||||
which are in folder svn/HW2/javali_tests/HW2_nop90
|
||||
|
||||
As they are mostly related to errors that haven't been triggered, each test should be separate, in order to generate all
|
||||
of the errors.
|
||||
|
||||
### Remaining
|
||||
### Done
|
||||
* access var from class or superclass
|
||||
* test ! operator
|
||||
* type error in unaryOp
|
||||
* type error in array size
|
||||
* call method from superclass
|
||||
* call a method that doesn't exist
|
||||
* call a method with the wrong type of params
|
||||
* call a method with the wrong number of params
|
||||
* assign to all possible syntactically correct options
|
||||
* field
|
||||
* var
|
||||
* array index
|
||||
* method (error)
|
||||
* this (error)
|
||||
* indexing both types error
|
||||
* try to access a field of something that is not a class type
|
||||
* typing error in cast
|
||||
* AND and OR operations
|
||||
* equals operators (a case that is OK and another that's not)
|
||||
* binary operation with wrong type (any but == and !=)
|
||||
* search for a type that doesn't exist in a method body
|
||||
* don't have a Main class
|
||||
* don't have a main() method in the Main class (all possibilities)
|
||||
* wrong name
|
||||
* wrong return value
|
||||
* wrong parameters
|
||||
* inherited main method (it should work)
|
||||
* write something that is not an integer
|
||||
* declare a variable mutiple times (local variables)
|
||||
* declare a local variable with the same name as a parameter
|
||||
* check MISSING_RETURN
|
||||
* nested ifElse as end of method
|
||||
* while as end of method
|
||||
* normal returns at the end of the method
|
||||
* return with further statements after it
|
||||
* while with non-int condition
|
||||
* use a array type that hasn't been discovered yet
|
||||
* ```class A { B[] name; } class B {}```
|
||||
* name a class Object
|
||||
* name a class like another class
|
||||
* name a parameter like another
|
||||
* override methods and try to break that
|
||||
* same return type
|
||||
* same number of params
|
||||
* same type of params
|
||||
* name a variable like another (field level)
|
||||
75
build.xml
75
build.xml
|
|
@ -1,4 +1,4 @@
|
|||
<project name="compiler-design" default="generate-parser" basedir="." xmlns:jacoco="antlib:org.jacoco.ant">
|
||||
<project name="compiler-design" default="test" basedir="." xmlns:jacoco="antlib:org.jacoco.ant">
|
||||
|
||||
<!-- A very simple ant file that primarily exists to run cup and lex;
|
||||
it also includes targets to build the compiler and run tests for those
|
||||
|
|
@ -8,55 +8,25 @@
|
|||
<property name="src.dir" value="${basedir}/src"/>
|
||||
<property name="test.dir" value="${basedir}/test"/>
|
||||
<property name="javali_tests.dir" value="${basedir}/javali_tests"/>
|
||||
<property name="parser.dir" value="${src.dir}/cd/frontend/parser"/>
|
||||
<property name="parser.jar" value="${basedir}/lib/javaliParserObf.jar"/>
|
||||
<property name="build.dir" value="${basedir}/bin"/>
|
||||
<property name="junit.jar" value="${basedir}/lib/junit-4.12.jar"/>
|
||||
<property name="hamcrest.jar" value="${basedir}/lib/hamcrest-core-1.3.jar"/>
|
||||
<property name="antlr.jar" value="${basedir}/lib/antlr-4.7.1-complete.jar"/>
|
||||
<property name="antlr.jar" value="${basedir}/lib/antlr-4.4-complete.jar"/>
|
||||
<property name="antlr.profile" value="false"/>
|
||||
<property name="antlr.report" value="false"/>
|
||||
<property name="jacocoant.jar" value="${basedir}/lib/jacocoant.jar"/>
|
||||
<property name="coverage.file" location="${build.dir}/jacoco.exec"/>
|
||||
<property name="min.coverage" value="0.5"/>
|
||||
<property name="coverage.check" value="cd.frontend.*:cd.backend.*"/>
|
||||
|
||||
<target name="generate-parser">
|
||||
<echo message="ANTLR4 ${parser.dir}/Javali.g4" level="info"/>
|
||||
<echo>${basedir}</echo>
|
||||
<java classname="org.antlr.v4.Tool" failonerror="true" classpath="${antlr.jar}">
|
||||
<arg value="${parser.dir}/Javali.g4" />
|
||||
<arg value="-o" />
|
||||
<arg value="${parser.dir}" />
|
||||
<arg value="-no-listener" />
|
||||
<arg value="-visitor" />
|
||||
</java>
|
||||
|
||||
</target>
|
||||
|
||||
<!-- Deletes the generated ANTLR parser files. Don't use in HW1! -->
|
||||
<target name="clean-parser">
|
||||
<delete file="${parser.dir}/Javali.tokens"/>
|
||||
<delete file="${parser.dir}/JavaliLexer.java"/>
|
||||
<delete file="${parser.dir}/JavaliParser.java"/>
|
||||
<delete file="${parser.dir}/JavaliWalker.tokens"/>
|
||||
<delete file="${parser.dir}/JavaliWalker.java"/>
|
||||
<delete file="${parser.dir}/JavaliBaseListener.java"/>
|
||||
<delete file="${parser.dir}/JavaliBaseVisitor.java"/>
|
||||
<delete file="${parser.dir}/JavaliListener.java"/>
|
||||
<delete file="${parser.dir}/JavaliVisitor.java"/>
|
||||
<delete file="${parser.dir}/JavaliLexer.tokens"/>
|
||||
<delete file="${parser.dir}/Javali.interp"/>
|
||||
<delete file="${parser.dir}/JavaliLexer.interp"/>
|
||||
</target>
|
||||
<property name="doc.dir" value="javadoc"/>
|
||||
|
||||
<!-- Cleans generated code, but NOT the parser source! -->
|
||||
<target name="clean">
|
||||
<delete dir="${build.dir}"/>
|
||||
</target>
|
||||
|
||||
<!-- Builds the compiler framework for HW > HW1. -->
|
||||
<target name="compile" depends="generate-parser">
|
||||
<target name="compile">
|
||||
<mkdir dir="${build.dir}"/>
|
||||
|
||||
<javac debug="true" destdir="${build.dir}" includeantruntime="false">
|
||||
|
|
@ -66,6 +36,7 @@
|
|||
<pathelement location="${antlr.jar}"/>
|
||||
<pathelement location="${junit.jar}"/>
|
||||
<pathelement location="${hamcrest.jar}"/>
|
||||
<pathelement location="${parser.jar}"/>
|
||||
</classpath>
|
||||
</javac>
|
||||
</target>
|
||||
|
|
@ -108,4 +79,40 @@
|
|||
<fail if="tests-failed" />
|
||||
</target>
|
||||
|
||||
<target name="test-coverage-report">
|
||||
<jacoco:report>
|
||||
<executiondata>
|
||||
<file file="${coverage.file}"/>
|
||||
</executiondata>
|
||||
|
||||
<structure name="JaCoCo Ant Example">
|
||||
<classfiles>
|
||||
<fileset dir="${build.dir}"/>
|
||||
</classfiles>
|
||||
<sourcefiles encoding="UTF-8">
|
||||
<fileset dir="${src.dir}"/>
|
||||
</sourcefiles>
|
||||
</structure>
|
||||
<check>
|
||||
<rule element="PACKAGE" includes="${coverage.check}">
|
||||
<limit counter="LINE" value="COVEREDRATIO" minimum="${min.coverage}"/>
|
||||
</rule>
|
||||
</check>
|
||||
</jacoco:report>
|
||||
<echo message="Coverage above ${min.coverage} in ${coverage.check}: OK" level="info"/>
|
||||
</target>
|
||||
|
||||
<target name="clean-doc">
|
||||
<delete dir="javadoc"/>
|
||||
</target>
|
||||
|
||||
<target name="generate-doc">
|
||||
<javadoc sourcepath="${src.dir}" destdir="${doc.dir}"
|
||||
private="true" use="true" author="true">
|
||||
<package name="cd"/>
|
||||
<package name="cd.frontend.semantic"/>
|
||||
<package name="cd.ir"/>
|
||||
<arg value="-notimestamp"/>
|
||||
</javadoc>
|
||||
</target>
|
||||
</project>
|
||||
|
|
|
|||
9
javali_tests/HW3/ErrCallBase.javali
Normal file
9
javali_tests/HW3/ErrCallBase.javali
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
// Test that you cannot invoke a method on an integer.
|
||||
|
||||
class Main {
|
||||
void main() {
|
||||
int x;
|
||||
x = 1;
|
||||
x.foo();
|
||||
}
|
||||
}
|
||||
9
javali_tests/HW3/ErrCircularInheritance.javali
Normal file
9
javali_tests/HW3/ErrCircularInheritance.javali
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
/* Test that the circular inheritance between Foo and Bar is detected */
|
||||
class Foo extends Bar { }
|
||||
class Bar extends Foo { }
|
||||
|
||||
class Main {
|
||||
void main() {
|
||||
writeln();
|
||||
}
|
||||
}
|
||||
11
javali_tests/HW3/ErrIfCondition.javali
Normal file
11
javali_tests/HW3/ErrIfCondition.javali
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
/* Test that if conditions must be boolean */
|
||||
class Main {
|
||||
void main() {
|
||||
if (84 / 2) {
|
||||
write(1);
|
||||
writeln();
|
||||
}
|
||||
write(2);
|
||||
writeln();
|
||||
}
|
||||
}
|
||||
14
javali_tests/HW3/ErrUnknownField1.javali
Normal file
14
javali_tests/HW3/ErrUnknownField1.javali
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
/* Test that an invalid field name is detected */
|
||||
|
||||
class X {
|
||||
int field;
|
||||
}
|
||||
|
||||
class Main {
|
||||
void main() {
|
||||
X x;
|
||||
x = new X();
|
||||
x.field = 0;
|
||||
x.notafield = 1; /* ILLEGAL: bad field name */
|
||||
}
|
||||
}
|
||||
30
javali_tests/HW3/OkInheritanceFields.javali
Normal file
30
javali_tests/HW3/OkInheritanceFields.javali
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
/* Test that fields are inherited */
|
||||
|
||||
class A {
|
||||
int foo;
|
||||
}
|
||||
|
||||
class B extends A {
|
||||
int bar;
|
||||
}
|
||||
|
||||
class Main {
|
||||
void main() {
|
||||
A a;
|
||||
B b;
|
||||
|
||||
a = new A();
|
||||
a.foo = 1;
|
||||
write(a.foo);
|
||||
|
||||
a = new B();
|
||||
a.foo = 2;
|
||||
write(a.foo);
|
||||
|
||||
b = new B();
|
||||
b.foo = 3;
|
||||
b.bar = 4;
|
||||
write(b.foo);
|
||||
write(b.bar);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
// Test that arrays are not covariant
|
||||
|
||||
class Main {
|
||||
void main() {
|
||||
boolean y;
|
||||
A[] Array1;
|
||||
B[] Array2;
|
||||
Array2 = new B[10];
|
||||
|
||||
Array1 = Array2;
|
||||
}
|
||||
}
|
||||
|
||||
class B extends A {}
|
||||
|
||||
class A {}
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
// The left-hand side of an assignment cannot be a method call
|
||||
// Valid options are variable accesses, fields or an indexed array
|
||||
|
||||
class Main {
|
||||
void main() {
|
||||
action() = read();
|
||||
}
|
||||
int action() {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
// The left-hand side of an assignment cannot be a reference to this
|
||||
// Valid options are variable accesses, fields or an indexed array
|
||||
|
||||
class Main {
|
||||
void main () {
|
||||
int b;
|
||||
int[] c;
|
||||
c = new int[5];
|
||||
this.a = 10;
|
||||
b = 10;
|
||||
c[4] = 10;
|
||||
this = null;
|
||||
}
|
||||
int a;
|
||||
}
|
||||
14
javali_tests/HW3_nop90/Assignments/OkArraySubtypes.javali
Normal file
14
javali_tests/HW3_nop90/Assignments/OkArraySubtypes.javali
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
// any array is a subtype of Object
|
||||
// assignment and 'is equal' with an object of type 'Object' is fine
|
||||
|
||||
class Main {
|
||||
void main() {
|
||||
boolean y;
|
||||
Object x;
|
||||
int[] testArray;
|
||||
testArray = new int[10];
|
||||
x = testArray;
|
||||
testArray = null;
|
||||
x = null;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
// Multiple classes can't share the same name
|
||||
|
||||
class Aclass {}
|
||||
class Aclass {}
|
||||
|
||||
class Main {
|
||||
void main() {}
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
// Two fields in a class cannot share the same name
|
||||
|
||||
class Main {
|
||||
void main() {}
|
||||
int a;
|
||||
Object b;
|
||||
Main a;
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue