Assignment 1#
rough notes based on spec
Overview#
Need to extend the A1 PL0 recursive descent compiler so it supports:
- set types like
setof R - set constructors like
{10, -3, 5, 10+1}:SR - set equality and inequality
- set union, intersection, and subtraction
- set complement using
~ - set membership using
in forstatements that iterate over the elements of a set- interpreter support for the new set operations and for loops
Basically:
Note
If the parser or AST shape is messy, the checker and interpreter will be painful. Keep It Simple, Stupid.
Strict Rules#
- Only change the allowed files
- Do not modify unrelated compiler files
- Do not reformat random existing code
- Do not touch unrelated files just because the IDE suggests it
- No imports outside
java.util.* - No debugging prints in final code
- Keep lines under 100 characters
- Avoid non-standard characters in submitted Java comments
- Avoid tabs or keep tab stops at 4 spaces
- Do not submit this
TODO.md - Need to add
UseOfAI.pdf
Allowed files:
ExpNode.javaExpTransform.javaInterpreter.javaParser.javaStatementNode.javaStatementVisitor.javaStaticChecker.javaType.javaUseOfAI.pdf
Rough Order of Adding Stuff#
- Recursive descent parser changes
- AST nodes + transform/visitor methods
- Set type and operator support
- Static checking
- Interpreter support
- Testing
- Cleanup +
UseOfAI.pdf
Tip
Get one tiny valid set program working end-to-end first, then check edge cases.
1. Parser#
File:
Parser.java
1.1 Easy setup checks#
- Lexer already has
LCURLYandRCURLY - Lexer already has
SET_COMPLEMENT - Lexer already has
KW_FOR - Lexer already has
KW_IN - Lexer already has
KW_SETOF - Confirm the parser can see the new tokens
- Keep parser changes close to the existing recursive descent style
- Keep syntax error recovery consistent with the existing parser
- Do not touch generated or unrelated lexer files
Caution
The scanner tokens are already provided for this assignment. The job here is the recursive descent parser, not scanner surgery.
1.2 Add set type syntax#
Need:
Type -> ... | SetType
SetType -> "setof" TypeIdentifier
- Extend type parsing with a set type alternative
- Parse
setoffollowed by a type identifier - Store the element type identifier
- Build a real set type representation
- Keep normal type identifiers working as before
- Keep subrange type parsing working as before
Important
The element type name is checked later. Do not make the parser do semantic work.
1.3 Add set constructor factors#
Need:
Factor -> ... | "{" [ Condition { "," Condition } ] "}" ":" TypeIdentifier
- Parse an empty set constructor
- Parse a set constructor with one expression
- Parse comma-separated constructor expressions
- Require the colon after the closing brace
- Store the set type identifier after the colon
- Store the element expressions in order
- Return a real expression node for the constructor
- Keep ordinary expression factors working as before
Examples:
{}:SR
{10}:SR
{10, -3, 5, 10+1}:SR
Warning
This looks a bit like a block, but it is an expression factor.
1.4 Add set complement factors#
Need:
Factor -> ... | "~" Factor
- Parse set complement as a factor
- Store the operand expression
- Make sure complement has higher precedence than binary set operators
- Keep existing unary and factor behaviour unchanged
Note
Complement binds tighter than set union, subtraction, and intersection.
1.5 Add set membership operator#
Need:
RelOp -> ... | "in"
- Add
inas a relational operator - Keep relational precedence lower than set arithmetic operators
- Make sure normal relational operators still parse correctly
- Make sure
i in sparses as a boolean-valued condition shape
Important
in is relational-level syntax, not another additive operator.
1.6 Check set operator precedence#
Need set operators to behave like:
+means set union*means set intersection-means set subtraction~means set complementinmeans set membership
Checklist:
- Keep set union and set subtraction left associative
- Keep set union and set subtraction at the same precedence
- Keep set intersection left associative
- Keep set intersection higher precedence than union and subtraction
- Keep set complement higher precedence than binary set operators
- Keep relational operators lower precedence than set operators
- Do not break numeric arithmetic precedence
Caution
The same symbols are used for both numeric and set operations, so parser precedence should stay boring and consistent.
1.7 Add for statement syntax#
Need:
Statement -> ... | SetForStatement
SetForStatement -> "for" IDENTIFIER ":" Condition "do" Statement
- Add
foras a statement start - Parse the control variable identifier
- Require the colon
- Parse the set expression after the colon
- Require
do - Parse the loop body statement
- Build a real for statement node
- Keep existing statement parsing and recovery working
Example:
for r : x do
write r
Note
The control variable is introduced by the for statement. It is not just a normal existing variable lookup.
1.8 Parser error recovery#
- Follow the existing recursive descent recovery style
- Add recovery sets for new set syntax where needed
- Add recovery sets for the for statement where needed
- Avoid parser crashes on malformed set constructors
- Avoid parser crashes on malformed for statements
- Run a few invalid syntax examples before moving on
Warning
Syntax error recovery is part of the A1 syntax-analysis mark, so do not leave the parser fragile.
2. AST#
Files:
ExpNode.javaExpTransform.javaStatementNode.javaStatementVisitor.java
2.1 Add set constructor expression support#
- Add an expression node for set constructors
- Store the set type name
- Store the element expression list
- Support an empty element list
- Leave name/type resolution for the checker
- Add transform support
- Add string/debug representation in the existing style
Tip
Let the checker resolve the type name. Keep parser-built nodes simple.
2.2 Add set complement expression support#
- Add expression support for set complement
- Store the operand expression
- Add transform support
- Add string/debug representation in the existing style
- Keep existing unary expression behaviour unchanged
Note
This is the new unary set operator.
2.3 Add set membership expression/operator support#
- Add expression/operator support for
in - Keep it in the same general expression structure as relational operators
- Store the left expression
- Store the right expression
- Add transform support if needed by the existing design
Important
Membership returns a boolean value, not a set value.
2.4 Add for statement support#
- Add a statement node for set for loops
- Store the control variable name
- Store the set expression
- Store the body statement
- Add statement visitor support
- Keep the node simple and avoid semantic checking inside it
Example shape:
for r : x do
write r
Note
The checker and interpreter handle the meaning. The AST should just preserve the structure.
2.5 Add visitor and transform methods#
- Add expression transform support for set constructors
- Add expression transform support for set complement
- Add expression/operator support for set membership if needed
- Add statement visitor support for set for loops
- Update default paths that would otherwise miss the new nodes
Warning
Forgetting one visitor or transform path is the classic instant compile failure.
3. Type and Operator Support#
File:
Type.java
3.1 Check existing set type support#
The spec says SetType has already been added in Type.java.
Checklist:
- Inspect the existing
SetTypeclass - Confirm how the element type is stored
- Confirm how
resolveTypechecks well-formedness - Confirm how set type equality is implemented
- Avoid rewriting existing working set type code
- Preserve existing behaviour for non-set types
Important
Do not replace provided support unless it is actually incomplete for the assignment task.
3.2 Validate set type declarations#
Set element types must be subrange types with at most 32 values.
Checklist:
- Reject set element types that are not subrange types
- Reject set element subranges with more than 32 values
- Allow valid subrange element types
- Preserve existing type alias behaviour
- Keep errors clear and source locations useful
Examples:
type R = [-3..11];
SR = setof R;
Note
The 32-element limit exists because set values fit in one 32-bit word.
3.3 Type equivalence for sets#
Two set types are equivalent when their element types are equivalent.
Example:
type R3 = [1..3];
A = setof R3;
B = A;
C = setof R3;
- Preserve existing type identifier and alias behaviour
- Treat equivalent element types as equivalent set types
- Allow assignments between equivalent set types
- Keep non-set type equivalence unchanged
Note
Follow the existing equals behaviour for resolved set types.
3.4 Add set operators#
Need operators for each declared set type:
= : T x T -> boolean
!= : T x T -> boolean
+ : T x T -> T
* : T x T -> T
- : T x T -> T
in : E x T -> boolean
~ : T -> T
Where:
T = setof E
Checklist:
- Add equality for equivalent set types
- Add inequality for equivalent set types
- Add set union
- Add set intersection
- Add set subtraction
- Add set membership
- Add set complement
- Keep numeric operators unchanged
- Keep boolean operators unchanged
Tip
Add only the operators required by the spec. No bonus language design side quests.
4. Static Checker#
File:
StaticChecker.java
4.1 Type-check set constructors#
Need:
{e1, e2, ..., en}:id
Checklist:
- Resolve the type identifier after the colon
- Make sure it names a set type
- Check every element expression
- Check every element expression is compatible with the set element type
- Allow repeated element expressions
- Allow empty set constructors when the type is known
- Set the constructor expression type to the named set type
- Give clear errors for unknown type identifiers
- Give clear errors for non-set type identifiers
- Give clear errors for wrong element types
Examples:
{}:SR
{10, -3, 5, 10+1}:SR
Important
The type annotation after the constructor is what gives the set its type.
4.2 Type-check set complement#
Need:
~s
Checklist:
- Check the operand expression
- Require the operand to have a set type
- Set the result type to the same set type
- Reject complement on non-set values
- Keep other unary expression behaviour unchanged
Note
Complement is a set-to-set operation.
4.3 Type-check set binary operators#
Need:
s1 + s2
s1 * s2
s1 - s2
Checklist:
- Check both operand expressions
- Require both operands to be set types
- Require compatible set types
- Set the result type to the set type
- Keep numeric uses of
+,*, and-working - Give clear errors for mixed numeric/set mistakes
- Give clear errors for incompatible set types
Caution
The same symbols are reused for arithmetic and sets, so old arithmetic tests must still pass.
4.4 Type-check set equality and inequality#
Need:
s1 = s2
s1 != s2
Checklist:
- Allow equality between compatible set types
- Allow inequality between compatible set types
- Result type is boolean
- Reject equality between incompatible set types
- Keep existing equality behaviour for non-set types unchanged
Note
Set equality means same elements, but the checker only needs the types.
4.5 Type-check set membership#
Need:
e in s
Checklist:
- Check the element expression
- Check the set expression
- Require the right side to have a set type
- Require the left side to be compatible with the set element type
- Set the result type to boolean
- Reject membership on non-set right-hand sides
- Give clear errors for incompatible element expressions
Important
in is not set-to-set. It is element-in-set.
4.6 Type-check for statements#
Need:
for id : e do s
Checklist:
- Check the set expression after the colon
- Require the expression to have a set type
- Treat the control variable as local to the for statement
- Give the control variable the set element type
- Make the control variable read-only inside the body
- Allow the control variable name to shadow an existing name
- Restore the previous binding after the body
- Type-check the loop body in the extended scope
- Reject assignments to the read-only control variable
- Keep nested for loops working
Warning
The control variable is read-only inside the loop body.
4.7 Error handling quality#
- Use the best source location available for each semantic error
- Do not crash after syntax errors leave partial AST pieces
- Prefer specific messages for non-set constructor types
- Prefer specific messages for wrong constructor element types
- Prefer specific messages for invalid set operators
- Prefer specific messages for invalid for-loop expressions
- Prefer specific messages for assignment to read-only control variables
- Match provided test outputs where possible
- Do not add random debugging text to compiler output
Caution
Automated tests may be strict about output for provided cases.
5. Interpreter#
File:
Interpreter.java
5.1 Runtime representation for sets#
A set value should represent membership over a small subrange domain.
Checklist:
- Represent set values as a single integer value
- Use one bit per possible element in the element subrange
- Preserve value-copy assignment behaviour for sets
- Keep existing scalar value behaviour unchanged
- Keep existing reference behaviour unchanged
Note
Sets are limited to at most 32 possible elements, so one integer can hold the whole set value.
5.2 Interpret set constructors#
Need:
{e1, e2, ..., en}:id
Checklist:
- Evaluate each element expression
- Convert each element value into the correct set position
- Add each element into the set value
- Allow repeated elements
- Allow empty set constructors
- Return a set value with the correct type information
Examples:
{}:SR
{10, -3, 5, 10+1}:SR
Important
Repeated elements are not runtime errors.
5.3 Interpret set union, intersection, and subtraction#
Need:
s1 + s2
s1 * s2
s1 - s2
Checklist:
- Evaluate both set operands
- Implement set union
- Implement set intersection
- Implement set subtraction
- Return a set value of the same set type
- Keep numeric arithmetic interpretation unchanged
Caution
Do not break old arithmetic while adding set arithmetic.
5.4 Interpret set complement#
Need:
~s
Checklist:
- Evaluate the set operand
- Compute complement relative to the set type's element domain
- Return a set value of the same set type
- Keep complement limited to valid elements of the set domain
Warning
Complement is relative to the declared set domain, not all integer bits.
5.5 Interpret set equality and inequality#
Need:
s1 = s2
s1 != s2
Checklist:
- Evaluate both set operands
- Compare set contents
- Return a boolean value
- Keep existing equality behaviour unchanged for non-set values
Note
Set equality is based on exactly the same elements being present.
5.6 Interpret set membership#
Need:
e in s
Checklist:
- Evaluate the element expression
- Evaluate the set expression
- Check whether the element is present in the set
- Return a boolean value
- Handle elements from the element type domain correctly
- Keep the result false when the element is not present
Important
Membership is a boolean-valued expression.
5.7 Interpret for statements#
Need:
for id : e do s
Runtime behaviour:
- the set expression is evaluated at the start of the loop
- the body runs once for each element in that initial set value
- elements are visited in increasing order
- changes to the set expression during the loop do not change the iteration set
- the control variable is assigned by the loop itself
Checklist:
- Evaluate the set expression once at the start
- Iterate over the initial set value
- Visit elements in increasing order
- Assign the control variable at the start of each iteration
- Execute the body once for each present element
- Keep the control variable read-only to user assignments
- Handle an empty set by executing the body zero times
- Keep nested for loops working
Warning
The loop iterates over the initial value of the set expression, not a live changing view of it.
6. Testing#
6.1 Basic test order#
- Run all provided base tests first
- Run all provided set/for tests
- Run tiny hand-written tests after every major feature
- If old tests break, check recent parser/checker/interpreter changes
- Run final tests from a clean rebuild
- Do not rely on stale runs or old compiled classes
Important
Regression tests matter because old arithmetic, references, and statements are easy to break while adding set features.
6.2 Syntax tests#
- Valid set type declaration
- Set constructor with no elements
- Set constructor with one element
- Set constructor with multiple elements
- Set constructor with repeated elements
- Set complement expression
- Set union expression
- Set intersection expression
- Set subtraction expression
- Set membership expression
- For statement over a set variable
- For statement over a set constructor
- Nested for statements
- Old PL0 syntax still parses
6.3 Static checking tests#
- Set type whose element type is a valid subrange
- Set type whose element type is not a subrange
- Set type whose element subrange has more than 32 values
- Constructor with valid element expressions
- Constructor with wrong element expression type
- Constructor using an unknown type identifier
- Constructor using a non-set type identifier
- Assignment between compatible set types
- Assignment between incompatible set types is rejected
- Set union with compatible set types
- Set intersection with compatible set types
- Set subtraction with compatible set types
- Set operators reject incompatible set types
- Set complement rejects non-set operands
- Set membership accepts valid element/set pairs
- Set membership rejects invalid element/set pairs
- Set equality and inequality work for compatible set types
- For loop accepts a set expression
- For loop rejects a non-set expression
- For control variable shadows existing variables correctly
- For control variable is read-only
- Old PL0 static checking tests still pass
6.4 Runtime/interpreter tests#
- Set constructor produces the expected set value
- Empty set constructor produces an empty set
- Repeated constructor elements only appear once
- Set assignment copies by value
- Reassigning source set does not mutate copied set
- Set union produces expected elements
- Set intersection produces expected elements
- Set subtraction produces expected elements
- Set complement produces expected elements within the domain
- Set equality returns true for same elements in different order
- Set equality returns false for different elements
- Set membership returns true for present elements
- Set membership returns false for absent elements
- For loop visits elements in increasing order
- For loop over an empty set runs zero times
- For loop uses the initial set value even if the set changes
- Nested for loops behave correctly
- Old PL0 interpreter tests still pass
7. Cleanup#
- Remove debug prints
- Check imports for IDE garbage
- Check there are no imports outside
java.util.* - Make sure only allowed files were edited
- Check line lengths are sensible
- Avoid tabs or keep tab stops at 4 spaces
- Do not reformat unrelated existing code
- Keep comments short and consistent with the existing codebase
- Avoid non-standard characters in comments
- Fix obvious comment typos introduced while working
- Check indentation of new code matches nearby code
- Run final tests from scratch
- Confirm all required files are ready
- Confirm no extra files are being submitted
- Confirm
UseOfAI.pdfexists and has the required AI/MT statement
Warning
UseOfAI.pdf is required even if no AI or MT was used.
Comments
Powered by GitHub issues