Remove plans for looping constructs -- we don't need em

This commit is contained in:
Linus Lee 2020-09-24 07:46:06 -04:00
parent 4b487e7a38
commit d7c1ae4f76
2 changed files with 49 additions and 23 deletions

View File

@ -110,6 +110,8 @@ const T = {
ExpertsClaim: Symbol('ExpertsClaim'), ExpertsClaim: Symbol('ExpertsClaim'),
ToBe: Symbol('ToBe'), ToBe: Symbol('ToBe'),
YouWontWantToMiss: Symbol('YouWontWantToMiss'), YouWontWantToMiss: Symbol('YouWontWantToMiss'),
TotallyRight: Symbol('TotallyRight'),
CompletelyWrong: Symbol('CompletelyWrong'),
IsActually: Symbol('IsActually'), IsActually: Symbol('IsActually'),
And: Symbol('And'), And: Symbol('And'),
Or: Symbol('Or'), Or: Symbol('Or'),
@ -122,12 +124,6 @@ const T = {
SmallerThan: Symbol('SmallerThan'), // < SmallerThan: Symbol('SmallerThan'), // <
ShockingDevelopment: Symbol('ShockingDevelopment'), ShockingDevelopment: Symbol('ShockingDevelopment'),
PleaseLikeAndSubscribe: Symbol('PleaseLikeAndSubscribe'), PleaseLikeAndSubscribe: Symbol('PleaseLikeAndSubscribe'),
// not implemented yet
StayTuned: Symbol('StayTuned'),
Unexpectedly: Symbol('Unexpectedly'),
TotallyRight: Symbol('TotallyRight'),
CompletelyWrong: Symbol('CompletelyWrong'),
} }
const BINARY_OPS = [ const BINARY_OPS = [
@ -256,15 +252,6 @@ function tokenize(prog) {
tokens.push(T.PleaseLikeAndSubscribe); tokens.push(T.PleaseLikeAndSubscribe);
break; break;
} }
case 'STAY': {
reader.expect('TUNED');
tokens.push(T.StayTuned);
break;
}
case 'UNEXPECTEDLY': {
tokens.push(T.Unexpectedly);
break;
}
case 'TOTALLY': { case 'TOTALLY': {
reader.expect('RIGHT'); reader.expect('RIGHT');
tokens.push(T.TotallyRight); tokens.push(T.TotallyRight);
@ -306,6 +293,7 @@ function tokenize(prog) {
const N = { const N = {
NumberLiteral: Symbol('NumberLiteral'), NumberLiteral: Symbol('NumberLiteral'),
StringLiteral: Symbol('StringLiteral'), StringLiteral: Symbol('StringLiteral'),
BoolLiteral: Symbol('BoolLiteral'),
FnDecl: Symbol('FnDecl'), FnDecl: Symbol('FnDecl'),
FnCall: Symbol('FnCall'), FnCall: Symbol('FnCall'),
Ident: Symbol('Ident'), Ident: Symbol('Ident'),
@ -327,6 +315,7 @@ class Parser {
* Ident * Ident
* NumberLiteral * NumberLiteral
* StringLiteral * StringLiteral
* BoolLiteral
* FnCall * FnCall
* FnDecl * FnDecl
* ExprGroup * ExprGroup
@ -379,6 +368,16 @@ class Parser {
return this.fnCall(ident); return this.fnCall(ident);
} }
return ident; return ident;
} else if (next === T.TotallyRight) {
return {
type: N.BoolLiteral,
val: true,
}
} else if (next === T.CompletelyWrong) {
return {
type: N.BoolLiteral,
val: false,
}
} else if (next === T.DiscoverHowTo) { } else if (next === T.DiscoverHowTo) {
// fn literal // fn literal
const fnName = this.tokens.next(); const fnName = this.tokens.next();
@ -460,7 +459,7 @@ class Parser {
return { return {
type: N.ProgEndExpr, type: N.ProgEndExpr,
} }
} else if (next == T.YouWontWantToMiss) { } else if (next === T.YouWontWantToMiss) {
// print expr // print expr
return { return {
type: N.PrintExpr, type: N.PrintExpr,
@ -585,15 +584,26 @@ class Environment {
const left = this.eval(node.left); const left = this.eval(node.left);
const right = this.eval(node.right); const right = this.eval(node.right);
switch (node.op) { switch (node.op) {
// TODO: other ops
case T.IsActually: case T.IsActually:
return left === right; return left === right;
case T.And:
return left && right;
case T.Or:
return left || right;
case T.Add: case T.Add:
return left + right; return left + right;
case T.Subtract: case T.Subtract:
return left - right; return left - right;
case T.Multiply: case T.Multiply:
return left * right; return left * right;
case T.Divide:
return left / right;
case T.Modulo:
return left % right;
case T.Beats:
return left > right;
case T.SmallerThan:
return left < right;
default: default:
throw new Error(`Runtime error: Unknown binary op ${node.op.toString()}`); throw new Error(`Runtime error: Unknown binary op ${node.op.toString()}`);
} }
@ -607,7 +617,11 @@ class Environment {
} }
} }
case N.ExprGroup: { case N.ExprGroup: {
let rv = false; // TODO: make null value? make this illegal? if (!node.exprs.length) {
throw new Error('Runtime error: Empty expression group with no expressions');
}
let rv;
for (const expr of node.exprs) { for (const expr of node.exprs) {
rv = this.eval(expr); rv = this.eval(expr);
} }
@ -622,7 +636,13 @@ class Environment {
break; break;
} }
case N.PrintExpr: { case N.PrintExpr: {
const val = this.eval(node.val); let val = this.eval(node.val);
// shim for boolean to-string's
if (val === true) {
val = 'TOTALLY RIGHT';
} else if (val === false) {
val = 'COMPLETELY WRONG';
}
this.runtime.print(val); this.runtime.print(val);
return val; return val;
} }

View File

@ -115,7 +115,7 @@ class App extends Component {
<a href="#" onclick=${evt => { <a href="#" onclick=${evt => {
evt.preventDefault(); evt.preventDefault();
this.render(); this.render();
}}>Rewrite headline!</a> }}>NEW headline!</a>
<a href="https://dotink.co/posts/tabloid/" <a href="https://dotink.co/posts/tabloid/"
target="_blank" noopener noreferer>Blog post</a> target="_blank" noopener noreferer>Blog post</a>
</nav> </nav>
@ -147,13 +147,17 @@ class App extends Component {
Declare a function by writing <code class="inline fixed Declare a function by writing <code class="inline fixed
block">DISCOVER HOW TO ... WITH</code>. Truly, a more block">DISCOVER HOW TO ... WITH</code>. Truly, a more
gripping way to declare a function can't possibly exist! gripping way to declare a function can't possibly exist!
</li> Similarly, assign to a variable with <code class="inline fixed
<li>
Assign to a variable by writing <code class="inline fixed
block">EXPERTS CLAIM ... TO BE</code>. On the Internet, block">EXPERTS CLAIM ... TO BE</code>. On the Internet,
anyone can be an expert, and Tabloid gives YOU the power to anyone can be an expert, and Tabloid gives YOU the power to
wield that responsibility and declare anything you'd like! wield that responsibility and declare anything you'd like!
</li> </li>
<li>
There are <strong>no built-in constructs for looping</strong>. The news
cycle is moving too fast! Nobody has time for yesterday's
loops or last week's break statements. If you must loop,
use recursion.
</li>
<li> <li>
To return from a function, simply write <code class="inline To return from a function, simply write <code class="inline
fixed block">SHOCKING DEVELOPMENT</code>! You're going fixed block">SHOCKING DEVELOPMENT</code>! You're going
@ -203,6 +207,8 @@ class App extends Component {
<li><code class="inline fixed block">END OF STORY</code> end a block scope</li> <li><code class="inline fixed block">END OF STORY</code> end a block scope</li>
<li><code class="inline fixed block">EXPERTS CLAIM...TO BE</code> declare or assign to a variable</li> <li><code class="inline fixed block">EXPERTS CLAIM...TO BE</code> declare or assign to a variable</li>
<li><code class="inline fixed block">YOU WON'T WANT TO MISS</code> print output</li> <li><code class="inline fixed block">YOU WON'T WANT TO MISS</code> print output</li>
<li><code class="inline fixed block">TOTALLY RIGHT</code> true</li>
<li><code class="inline fixed block">COMPLETELY WRONG</code> false</li>
<li><code class="inline fixed block">IS ACTUALLY</code> is equal to</li> <li><code class="inline fixed block">IS ACTUALLY</code> is equal to</li>
<li><code class="inline fixed block">BEATS / SMALLER THAN</code> greater than / less than</li> <li><code class="inline fixed block">BEATS / SMALLER THAN</code> greater than / less than</li>
<li><code class="inline fixed block">SHOCKING DEVELOPMENT</code> return from a function</li> <li><code class="inline fixed block">SHOCKING DEVELOPMENT</code> return from a function</li>