summaryrefslogtreecommitdiff
path: root/chapter24a/src/main/java/com/seaofnodes
diff options
context:
space:
mode:
authorCliff Click <cliffc@acm.org>2026-10-25 09:51:44 -0700
committerCliff Click <cliffc@acm.org>2026-10-25 09:51:44 -0700
commit4051ce7cd26314f01dc8c0237899a742e0ab2084 (patch)
tree29cb9b47e0461c34be1797ac36dd31e8f0b10c09 /chapter24a/src/main/java/com/seaofnodes
parent5cfb046c8306a81ec40be82a59015f16f654fa93 (diff)
downloadSimple-4051ce7cd26314f01dc8c0237899a742e0ab2084.tar.gz
Simple-4051ce7cd26314f01dc8c0237899a742e0ab2084.zip
Fix ++x in methods
Fix ideaj setups
Diffstat (limited to 'chapter24a/src/main/java/com/seaofnodes')
-rw-r--r--chapter24a/src/main/java/com/seaofnodes/simple/Parser.java52
1 files changed, 29 insertions, 23 deletions
diff --git a/chapter24a/src/main/java/com/seaofnodes/simple/Parser.java b/chapter24a/src/main/java/com/seaofnodes/simple/Parser.java
index 81c7be32..7a67c096 100644
--- a/chapter24a/src/main/java/com/seaofnodes/simple/Parser.java
+++ b/chapter24a/src/main/java/com/seaofnodes/simple/Parser.java
@@ -1246,19 +1246,17 @@ public class Parser {
// Pre-dec/pre-inc
int old = pos();
if( match("--") || match("++") ) {
- int delta = _lexer.peek(-1)=='+' ? 1 : -1; // Pre vs post
+ int delta = _lexer.peek(-1)=='+' ? 1 : -1; // Inc vs Dec
+ int start = pos();
String name = _lexer.matchId();
- if( name!=null ) {
- Var n = _scope.lookup(name);
- if( n != null && !(n.type() instanceof TypeMemPtr) ) {
- if( n._final )
- throw error("Cannot reassign final '"+n._name+"'");
- Node expr = n.type() instanceof TypeFloat
- ? peep(new AddFNode(_scope.in(n),con(TypeFloat.constant(delta))))
- : zsMask(peep(new AddNode(_scope.in(n),con(delta))),n.type());
- _scope.update(n,expr);
- return expr;
- }
+ Var var = name==null ? null : _scope.lookup(name);
+ if( var!=null && !(var.type() instanceof TypeMemPtr) ) {
+ if( var._final )
+ throw error("Cannot reassign final '"+var._name+"'");
+ // Resolve fields just as a read or postfix update does. Updating
+ // their declaration's local slot would silently lose the Store.
+ pos(start);
+ return parsePrimary(delta);
}
// Reset, try again
pos(old);
@@ -1279,7 +1277,10 @@ public class Parser {
* </pre>
* @return a primary {@link Node}, never {@code null}
*/
- private Node parsePrimary() {
+ private Node parsePrimary() { return parsePrimary(0); }
+
+ // pre is +/-1 for a prefix update of a known name, zero otherwise.
+ private Node parsePrimary(int pre) {
if( _lexer.isNumber(_lexer.peek()) ) return parseLiteral();
if( _lexer.peek('"') ) return newString(parseString());
if( matchx("true" ) ) return con(1);
@@ -1326,7 +1327,7 @@ public class Parser {
// Else safety check for accessing fields out of function scope.
if( instance(var) ) {
Node self = _scope.in(_scope.lookup("self")); // Insert self reference
- return parsePostfixName(self,id);
+ return parsePostfixName(self,id,pre);
}
// Load local value
@@ -1337,7 +1338,7 @@ public class Parser {
else throw error("Cannot read uninitialized field '"+id+"'");
// Check for assign-update, x += e0;
- char ch = _lexer.matchOperAssign();
+ char ch = pre==0 ? _lexer.matchOperAssign() : (char)pre;
if( ch==0 ) // Normal primary, check for postfix updates
return parsePostfix(rvalue);
// Assign-update direct into Scope
@@ -1345,7 +1346,8 @@ public class Parser {
throw error("Cannot reassign final '"+var._name+"'");
Node op = opAssign(ch,rvalue, var.type() );
_scope.update(var,op);
- return postfix(ch) ? rvalue.unkeep() : op;
+ if( postfix(ch) ) rvalue.unkeep();
+ return pre==0 && postfix(ch) ? rvalue : op;
}
// true if instance variable lookup (var is in any number of nested blocks,
@@ -1574,7 +1576,9 @@ public class Parser {
* expr ('[' expr ']')* [ [op]= expr ] // Array reference
* </pre>
*/
- private Node parsePostfixName(Node expr, String name) {
+ private Node parsePostfixName(Node expr, String name) { return parsePostfixName(expr,name,0); }
+
+ private Node parsePostfixName(Node expr, String name, int pre) {
if( expr._type==Type.NIL )
throw error("Accessing unknown field '" + name + "' from 'null'");
@@ -1609,7 +1613,7 @@ public class Parser {
: off(base,name)).keep();
// Disambiguate "obj.fld==x" boolean test from "obj.fld=x" field assignment
- if( matchOpx('=','=') ) {
+ if( pre==0 && matchOpx('=','=') ) {
Node val = parseAsgn().keep();
Node lift = liftExpr( val, tf, false );
@@ -1628,14 +1632,16 @@ public class Parser {
load = peep(load);
// Check for assign-update, "ptr.fld += expr" or "ary[idx]++"
- char ch = _lexer.matchOperAssign();
+ char ch = pre==0 ? _lexer.matchOperAssign() : (char)pre;
if( ch!=0 ) {
Node op = opAssign(ch,load,tf);
+ // A narrow Store may drop its conversion; prefix still returns it.
+ if( pre!=0 ) op.keep();
store(name,f._alias,tf,expr.unkeep(),off.unkeep(),op,false,base.isAry() ? ctrl() : null);
- load = postfix(ch) ? load.unkeep() : op;
- // And use the original loaded value as the result
- return load;
- //throw Utils.TODO(); // NO POSTFIX AFTER STORE, JUST RETURN
+ if( pre!=0 ) op.unkeep();
+ if( postfix(ch) ) load.unkeep();
+ // Prefix returns the new value; postfix returns the old load.
+ return pre==0 && postfix(ch) ? load : op;
} else {
off.unkill();
// Method call: Loaded a function from a named field, AND the base