ether-code 0.8.4 → 0.8.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/cli/ether.js CHANGED
@@ -6,7 +6,7 @@ const http = require('http')
6
6
  const { EtherCompiler } = require('./compiler')
7
7
  const { Watcher } = require('./watcher')
8
8
 
9
- const VERSION = '0.8.4'
9
+ const VERSION = '0.8.5'
10
10
 
11
11
  const COLORS = {
12
12
  reset: '\x1b[0m',
@@ -519,7 +519,7 @@ class PHPGenerator {
519
519
  }
520
520
 
521
521
  generateIfStatement(node) {
522
- const test = this.generateNode(node.test)
522
+ const test = this.generateNode(node.test || node.condition)
523
523
  this.writeLine(`if (${test}) {`)
524
524
  this.indent++
525
525
  this.generateNode(node.consequent)
@@ -527,7 +527,7 @@ class PHPGenerator {
527
527
 
528
528
  if (node.alternate) {
529
529
  if (node.alternate.type === 'IfStatement') {
530
- this.write('} else')
530
+ this.write('} else ')
531
531
  this.generateIfStatement({ ...node.alternate, isElseIf: true })
532
532
  } else {
533
533
  this.writeLine('} else {')
@@ -566,7 +566,7 @@ class PHPGenerator {
566
566
  }
567
567
 
568
568
  generateWhileStatement(node) {
569
- const test = this.generateNode(node.test)
569
+ const test = this.generateNode(node.test || node.condition)
570
570
  this.writeLine(`while (${test}) {`)
571
571
  this.indent++
572
572
  this.generateNode(node.body)
@@ -579,7 +579,7 @@ class PHPGenerator {
579
579
  this.indent++
580
580
  this.generateNode(node.body)
581
581
  this.indent--
582
- const test = this.generateNode(node.test)
582
+ const test = this.generateNode(node.test || node.condition)
583
583
  this.writeLine(`} while (${test});`)
584
584
  }
585
585
 
@@ -812,21 +812,21 @@ class PHPGenerator {
812
812
  }
813
813
 
814
814
  generateUnaryExpression(node) {
815
- const argument = this.generateNode(node.argument)
815
+ const argument = this.generateNode(node.argument || node.operand)
816
816
  let op = node.operator
817
817
  if (op === 'non' || op === 'not') op = '!'
818
818
 
819
- if (node.prefix) {
819
+ if (node.prefix !== false) {
820
820
  return `${op}${argument}`
821
821
  }
822
822
  return `${argument}${op}`
823
823
  }
824
824
 
825
825
  generateUpdateExpression(node) {
826
- const argument = this.generateNode(node.argument)
826
+ const argument = this.generateNode(node.argument || node.operand)
827
827
  const op = node.operator
828
828
 
829
- if (node.prefix) {
829
+ if (node.prefix !== false) {
830
830
  return `${op}${argument}`
831
831
  }
832
832
  return `${argument}${op}`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ether-code",
3
- "version": "0.8.4",
3
+ "version": "0.8.5",
4
4
  "description": "Ether - Le langage intentionnel",
5
5
  "main": "cli/compiler.js",
6
6
  "bin": {
@@ -1158,6 +1158,7 @@ class EtherParserPHP extends EtherParserBase {
1158
1158
  let variadic = false
1159
1159
  let byReference = false
1160
1160
  let defaultValue = null
1161
+ let name = null
1161
1162
 
1162
1163
  const val = this.current() ? this.normalizeAccents(String(this.current().value).toLowerCase()) : ''
1163
1164
  if (this.phpVisibility.includes(val)) {
@@ -1171,16 +1172,6 @@ class EtherParserPHP extends EtherParserBase {
1171
1172
  this.advance()
1172
1173
  }
1173
1174
 
1174
- const currentType = this.current()
1175
- if (currentType && currentType.type === TokenType.IDENTIFIER) {
1176
- const typeLower = this.normalizeAccents(String(currentType.value).toLowerCase())
1177
- if (this.phpTypes[typeLower] || typeLower[0] === typeLower[0].toUpperCase()) {
1178
- if (!this.peek(1) || this.peek(1).type !== TokenType.EQUALS) {
1179
- typeHint = this.parseTypeHint(lang)
1180
- }
1181
- }
1182
- }
1183
-
1184
1175
  if (this.match(TokenType.SPREAD) || this.matchValue('...')) {
1185
1176
  variadic = true
1186
1177
  }
@@ -1189,14 +1180,34 @@ class EtherParserPHP extends EtherParserBase {
1189
1180
  byReference = true
1190
1181
  }
1191
1182
 
1192
- const nameToken = this.current()
1193
- if (!nameToken) return null
1183
+ const currentToken = this.current()
1184
+ if (!currentToken) return null
1185
+
1186
+ const nextToken = this.peek(1)
1194
1187
 
1195
- let name = this.safeStr(nameToken.value)
1196
- if (name.startsWith('$')) {
1197
- name = name.substring(1)
1188
+ if (nextToken && nextToken.type === TokenType.COLON) {
1189
+ name = this.safeStr(currentToken.value)
1190
+ if (name.startsWith('$')) name = name.substring(1)
1191
+ this.advance()
1192
+ this.advance()
1193
+ typeHint = this.parseTypeHint(lang)
1194
+ } else {
1195
+ const typeLower = this.normalizeAccents(String(currentToken.value).toLowerCase())
1196
+ if (this.phpTypes[typeLower] || /^[A-Z]/.test(currentToken.value)) {
1197
+ typeHint = this.parseTypeHint(lang)
1198
+ }
1199
+
1200
+ const nameToken = this.current()
1201
+ if (nameToken && nameToken.type === TokenType.IDENTIFIER) {
1202
+ name = this.safeStr(nameToken.value)
1203
+ if (name.startsWith('$')) name = name.substring(1)
1204
+ this.advance()
1205
+ }
1206
+ }
1207
+
1208
+ if (!name) {
1209
+ name = 'param'
1198
1210
  }
1199
- this.advance()
1200
1211
 
1201
1212
  if (this.match(TokenType.EQUALS)) {
1202
1213
  defaultValue = this.parseExpression(lang)
@@ -1312,9 +1323,10 @@ class EtherParserPHP extends EtherParserBase {
1312
1323
  condition = this.parseExpression(lang)
1313
1324
  this.match(TokenType.RPAREN)
1314
1325
  } else {
1315
- condition = this.parseExpression(lang)
1326
+ condition = this.parseConditionUntilColon(lang)
1316
1327
  }
1317
1328
 
1329
+ this.match(TokenType.COLON)
1318
1330
  this.skipNewlines()
1319
1331
  const consequent = this.parseBlock(lang)
1320
1332
 
@@ -1322,31 +1334,64 @@ class EtherParserPHP extends EtherParserBase {
1322
1334
  this.skipNewlines()
1323
1335
 
1324
1336
  const elseVal = this.current() ? this.normalizeAccents(String(this.current().value).toLowerCase()) : ''
1325
- if (elseVal === 'sinon si' || elseVal === 'elseif') {
1326
- this.advance()
1327
- alternate = this.parseConditional(lang)
1328
- alternate.type = 'ElseIfStatement'
1329
- } else if (elseVal === 'sinon' || elseVal === 'else') {
1337
+ if (elseVal === 'sinon') {
1330
1338
  this.advance()
1331
1339
 
1332
1340
  const nextVal = this.current() ? this.normalizeAccents(String(this.current().value).toLowerCase()) : ''
1333
1341
  if (nextVal === 'si' || nextVal === 'if') {
1334
1342
  alternate = this.parseConditional(lang)
1335
- alternate.type = 'ElseIfStatement'
1343
+ alternate.type = 'IfStatement'
1336
1344
  } else {
1345
+ this.match(TokenType.COLON)
1337
1346
  this.skipNewlines()
1338
1347
  alternate = this.parseBlock(lang)
1339
1348
  }
1349
+ } else if (elseVal === 'else') {
1350
+ this.advance()
1351
+ this.match(TokenType.COLON)
1352
+ this.skipNewlines()
1353
+ alternate = this.parseBlock(lang)
1340
1354
  }
1341
1355
 
1342
1356
  return {
1343
1357
  type: 'IfStatement',
1344
- condition: condition,
1358
+ test: condition,
1345
1359
  consequent: consequent,
1346
1360
  alternate: alternate
1347
1361
  }
1348
1362
  }
1349
1363
 
1364
+ parseConditionUntilColon(lang) {
1365
+ const startPos = this.pos
1366
+ let depth = 0
1367
+
1368
+ while (!this.isAtEnd()) {
1369
+ const token = this.current()
1370
+ if (!token) break
1371
+
1372
+ if (token.type === TokenType.LPAREN) depth++
1373
+ if (token.type === TokenType.RPAREN) depth--
1374
+
1375
+ if (depth === 0 && token.type === TokenType.COLON) {
1376
+ break
1377
+ }
1378
+ if (depth === 0 && token.type === TokenType.NEWLINE) {
1379
+ break
1380
+ }
1381
+
1382
+ this.advance()
1383
+ }
1384
+
1385
+ const endPos = this.pos
1386
+ this.pos = startPos
1387
+
1388
+ if (endPos > startPos) {
1389
+ return this.parseExpression(lang)
1390
+ }
1391
+
1392
+ return { type: 'Literal', value: true }
1393
+ }
1394
+
1350
1395
  parseLoop(lang) {
1351
1396
  const token = this.current()
1352
1397
  const value = this.normalizeAccents(String(token.value).toLowerCase())
@@ -1385,7 +1430,7 @@ class EtherParserPHP extends EtherParserBase {
1385
1430
 
1386
1431
  parseFor(lang) {
1387
1432
  this.advance()
1388
-
1433
+
1389
1434
  let init = null
1390
1435
  let test = null
1391
1436
  let update = null
@@ -1405,8 +1450,23 @@ class EtherParserPHP extends EtherParserBase {
1405
1450
  update = this.parseExpression(lang)
1406
1451
  }
1407
1452
  this.match(TokenType.RPAREN)
1453
+ } else {
1454
+ if (!this.check(TokenType.SEMICOLON) && !this.check(TokenType.COLON)) {
1455
+ init = this.parseExpression(lang)
1456
+ }
1457
+ this.match(TokenType.SEMICOLON)
1458
+
1459
+ if (!this.check(TokenType.SEMICOLON) && !this.check(TokenType.COLON)) {
1460
+ test = this.parseExpression(lang)
1461
+ }
1462
+ this.match(TokenType.SEMICOLON)
1463
+
1464
+ if (!this.check(TokenType.COLON) && !this.check(TokenType.NEWLINE)) {
1465
+ update = this.parseExpression(lang)
1466
+ }
1408
1467
  }
1409
1468
 
1469
+ this.match(TokenType.COLON)
1410
1470
  this.skipNewlines()
1411
1471
  const body = this.parseBlock(lang)
1412
1472
 
@@ -1450,7 +1510,7 @@ class EtherParserPHP extends EtherParserBase {
1450
1510
  }
1451
1511
 
1452
1512
  const valueVar = this.current()
1453
- let value = this.safeStr(valueVar ? valueVar.value : 'value')
1513
+ value = this.safeStr(valueVar ? valueVar.value : 'value')
1454
1514
  if (value.startsWith('$')) value = value.substring(1)
1455
1515
  this.advance()
1456
1516
  } else {
@@ -1458,8 +1518,44 @@ class EtherParserPHP extends EtherParserBase {
1458
1518
  }
1459
1519
 
1460
1520
  this.match(TokenType.RPAREN)
1521
+ } else {
1522
+ const arrayToken = this.current()
1523
+ if (arrayToken) {
1524
+ array = { type: 'Identifier', name: this.safeStr(arrayToken.value) }
1525
+ this.advance()
1526
+ }
1527
+
1528
+ const asVal = this.current() ? this.normalizeAccents(String(this.current().value).toLowerCase()) : ''
1529
+ if (asVal === 'comme' || asVal === 'as') {
1530
+ this.advance()
1531
+ }
1532
+
1533
+ if (this.match(TokenType.AMPERSAND)) {
1534
+ byRef = true
1535
+ }
1536
+
1537
+ const firstVar = this.current()
1538
+ let firstName = this.safeStr(firstVar ? firstVar.value : 'item')
1539
+ if (firstName.startsWith('$')) firstName = firstName.substring(1)
1540
+ this.advance()
1541
+
1542
+ if (this.match(TokenType.DOUBLE_ARROW) || this.matchValue('=>')) {
1543
+ key = firstName
1544
+
1545
+ if (this.match(TokenType.AMPERSAND)) {
1546
+ byRef = true
1547
+ }
1548
+
1549
+ const valueVar = this.current()
1550
+ value = this.safeStr(valueVar ? valueVar.value : 'value')
1551
+ if (value.startsWith('$')) value = value.substring(1)
1552
+ this.advance()
1553
+ } else {
1554
+ value = firstName
1555
+ }
1461
1556
  }
1462
1557
 
1558
+ this.match(TokenType.COLON)
1463
1559
  this.skipNewlines()
1464
1560
  const body = this.parseBlock(lang)
1465
1561
 
@@ -1479,15 +1575,16 @@ class EtherParserPHP extends EtherParserBase {
1479
1575
  condition = this.parseExpression(lang)
1480
1576
  this.match(TokenType.RPAREN)
1481
1577
  } else {
1482
- condition = this.parseExpression(lang)
1578
+ condition = this.parseConditionUntilColon(lang)
1483
1579
  }
1484
1580
 
1581
+ this.match(TokenType.COLON)
1485
1582
  this.skipNewlines()
1486
1583
  const body = this.parseBlock(lang)
1487
1584
 
1488
1585
  return {
1489
1586
  type: 'WhileStatement',
1490
- condition: condition,
1587
+ test: condition,
1491
1588
  body: body
1492
1589
  }
1493
1590
  }