Fixed issues with some grammatical constructs, updated copyright year and minor changes to funDecl

This commit is contained in:
Nocturn9x 2022-03-11 16:03:51 +01:00
parent 8e94891d37
commit 9babc75995
19 changed files with 83 additions and 54 deletions

View File

@ -98,7 +98,7 @@ awaitStmt → "await" expression ";"; // Pauses the execution of the cal
// to the given name. The finally clause, if present, is executed regardless of whether the try block raises an exception, meaning it even overrides return,
// break and continue statements and it must be below all except clauses. The else clause, if present, is executed when the try block doesn't raise an exception.
// It must be the last statement of the block. A bare except clause without an exception name acts as a catch-all and must be placed below any other except clauses
tryStmt → "try" statement (("except" expression? statement)+ "finally" statement | "finally" statement)? ("else" statement)?;
tryStmt → "try" statement (except+ "finally" statement | "finally" statement | "else" statement | except+ "else" statement | except+ "else" statement "finally" statement);
blockStmt → "{" declaration* "}"; // Blocks create a new scope that lasts until they're closed
ifStmt → "if" "(" expression ")" statement ("else" statement)?; // If statements are conditional jumps
whileStmt → "while" "(" expression ")" statement; // While loops run until their condition is truthy
@ -133,6 +133,8 @@ lambda → ("(" parameters? ")")? blockStmt
parameters → IDENTIFIER ("," IDENTIFIER)*;
arguments → expression ("," expression)*;
declModifiers → ("private" | "public")? ("static" | "dynamic")?
except → ("except" expression? statement)
// Lexical grammar that defines terminals in a non-recursive (regular) fashion
COMMENT → "#" UNICODE* LF;
@ -146,7 +148,7 @@ BIN → "0b" ("0" | "1")+;
OCT → "0o" ("0" ... "7")+;
HEX → "0x" ("0" ... "9" | "A" ... "F" | "a" ... "f")+;
NUMBER → DECIMAL | FLOAT | BIN | HEX | OCT; // Numbers encompass integers, floats (even stuff like 1e5), binary numbers, hex numbers and octal numbers
STRING → ("r"|"b"|"f") SINGLESTRING | DOUBLESTRING | SINGLEMULTI | DOUBLEMULTI; // Encompasses all strings
STRING → ("r"|"b"|"f")? SINGLESTRING | DOUBLESTRING | SINGLEMULTI | DOUBLEMULTI; // Encompasses all strings
IDENTIFIER → ALPHA (ALPHA | DIGIT)*; // Valid identifiers are only alphanumeric!
QUOTE → "'";
DOUBLEQUOTE → "\"";

View File

@ -1,4 +1,4 @@
# Copyright 2021 Mattia Giambirtone & All Contributors
# Copyright 2022 Mattia Giambirtone & All Contributors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.

View File

@ -1,4 +1,4 @@
# Copyright 2021 Mattia Giambirtone & All Contributors
# Copyright 2022 Mattia Giambirtone & All Contributors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.

View File

@ -1,4 +1,4 @@
# Copyright 2021 Mattia Giambirtone & All Contributors
# Copyright 2022 Mattia Giambirtone & All Contributors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.

View File

@ -1,4 +1,4 @@
# Copyright 2021 Mattia Giambirtone & All Contributors
# Copyright 2022 Mattia Giambirtone & All Contributors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.

View File

@ -1,4 +1,4 @@
# Copyright 2021 Mattia Giambirtone & All Contributors
# Copyright 2022 Mattia Giambirtone & All Contributors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@ -38,7 +38,7 @@ const DEBUG_TRACE_GC* = false # Traces the garbage collector (TODO)
const DEBUG_TRACE_ALLOCATION* = false # Traces memory allocation/deallocation
const DEBUG_TRACE_COMPILER* = false # Traces the compiler
const JAPL_VERSION_STRING* = &"JAPL {JAPL_VERSION.major}.{JAPL_VERSION.minor}.{JAPL_VERSION.patch} {JAPL_RELEASE} ({JAPL_BRANCH}, {CompileDate}, {CompileTime}, {JAPL_COMMIT_HASH[0..8]}) [Nim {NimVersion}] on {hostOS} ({hostCPU})"
const HELP_MESSAGE* = """The JAPL programming language, Copyright (C) 2021 Mattia Giambirtone & All Contributors
const HELP_MESSAGE* = """The JAPL programming language, Copyright (C) 2022 Mattia Giambirtone & All Contributors
This program is free software, see the license distributed with this program or check
http://www.apache.org/licenses/LICENSE-2.0 for more info.

View File

@ -1,4 +1,4 @@
# Copyright 2021 Mattia Giambirtone & All Contributors
# Copyright 2022 Mattia Giambirtone & All Contributors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@ -924,13 +924,27 @@ proc statement(self: Compiler, node: ASTNode) =
proc funDecl(self: Compiler, node: FunDecl) =
## Compiles function declarations
# We store the current function...
# We store the current function
var function = self.currentFunction
self.currentFunction = node
# Declares the function's name in the
# outer scope...
self.declareName(node.name)
self.scopeDepth += 1
# ... but its arguments in an inner one!
# (this ugly part is needed because
# self.blockStmt() already increments
# and decrements the scope depth)
for argument in node.arguments:
self.declareName(IdentExpr(argument))
self.scopeDepth -= 1
# TODO: Default arguments
# A function's code is just compiled linearly
# and then jumped over
let jmp = self.emitJump(JumpForwards)
# Since the deferred array is a linear
# sequence of instructions and we want
# to keep track to whose function's each
@ -941,26 +955,37 @@ proc funDecl(self: Compiler, node: FunDecl) =
# the try/finally block with the deferred
# code
var deferStart = self.deferred.len()
self.blockStmt(BlockStmt(node.body))
# Yup, we're done. That was easy, huh?
# But after all functions are just named
# scopes, and we compile them just like that:
# we declare their name (before compiling them
# so recursion & co. works) and then just compile
# their body as a block statement (which takes
# we declare their name and arguments (before
# their body so recursion works) and then just
# handle them as a block statement (which takes
# care of incrementing self.scopeDepth so locals
# are resolved properly). There's a need for a bit
# of boilerplate code to make closures work, but
# that's about it
# All functions implicitly return nil
self.emitBytes(OpCode.Nil, OpCode.Return)
# All functions implicitly return nil. This code
# will not execute if there's an explicit return
# and I cannot figure out an elegant and simple
# way to tell if a function already returns
# or not, so we just play it safe
if not self.enableOptimizations:
self.emitBytes(OpCode.Nil, OpCode.Return)
else:
self.emitBytes(ImplicitReturn)
# Currently defer is not functional so we
# just pop the instructions
for i in countup(deferStart, self.deferred.len(), 1):
self.deferred.delete(i)
self.patchJump(jmp)
# ... and restore it later!
# This makes us compile nested functions correctly
self.currentFunction = function

View File

@ -1,4 +1,4 @@
# Copyright 2021 Mattia Giambirtone & All Contributors
# Copyright 2022 Mattia Giambirtone & All Contributors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.

View File

@ -1,4 +1,4 @@
# Copyright 2021 Mattia Giambirtone & All Contributors
# Copyright 2022 Mattia Giambirtone & All Contributors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.

View File

@ -1,4 +1,4 @@
# Copyright 2021 Mattia Giambirtone & All Contributors
# Copyright 2022 Mattia Giambirtone & All Contributors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@ -149,10 +149,11 @@ type
BuildSet,
BuildTuple,
## Misc
Assert,
MakeClass,
Slice, # Slices an object (takes 3 arguments: start, stop, step) and pushes the result of a.subscript(b, c, d) onto the stack
GetItem, # Pushes the result of a.getItem(b)
Assert, # Raises an AssertionFailed exception if the value at the top of the stack is falsey
MakeClass, # Builds a class instance from the values at the top of the stack (class object, constructor arguments, etc.)
Slice, # Slices an object (takes 3 arguments: start, stop, step). Pushes the result of a.subscript(b, c, d) onto the stack
GetItem, # Pushes the result of a.getItem(b) onto the stack
ImplicitReturn, # Optimization for returning nil from functions (saves us a VM "clock cycle")
# We group instructions by their operation/operand types for easier handling when debugging
@ -172,7 +173,7 @@ const simpleInstructions* = {Return, BinaryAdd, BinaryMultiply,
LessOrEqual, BinaryOr, BinaryAnd,
UnaryNot, BinaryFloorDiv, BinaryOf, Raise,
ReRaise, BeginTry, FinishTry, Yield, Await,
MakeClass}
MakeClass, ImplicitReturn}
# Constant instructions are instructions that operate on the bytecode constant table
const constantInstructions* = {LoadConstant, DeclareName, LoadName, StoreName, DeleteName}
@ -257,27 +258,28 @@ proc findOrAddConstant(self: Chunk, constant: ASTNode): int =
## Small optimization function that reuses the same constant
## if it's already been written before (only if self.reuseConsts
## equals true)
if self.reuseConsts:
for i, c in self.consts:
# We cannot use simple equality because the nodes likely have
# different token objects with different values
if c.kind != constant.kind:
continue
if constant.isConst():
var c = LiteralExpr(c)
var constant = LiteralExpr(constant)
if c.literal.lexeme == constant.literal.lexeme:
# This wouldn't work for stuff like 2e3 and 2000.0, but those
# forms are collapsed in the compiler before being written
# to the constants table
return i
elif constant.kind == identExpr:
var c = IdentExpr(c)
var constant = IdentExpr(constant)
if c.name.lexeme == constant.name.lexeme:
return i
else:
continue
if not self.reuseConsts:
return
for i, c in self.consts:
# We cannot use simple equality because the nodes likely have
# different token objects with different values
if c.kind != constant.kind:
continue
if constant.isConst():
var c = LiteralExpr(c)
var constant = LiteralExpr(constant)
if c.literal.lexeme == constant.literal.lexeme:
# This wouldn't work for stuff like 2e3 and 2000.0, but those
# forms are collapsed in the compiler before being written
# to the constants table
return i
elif constant.kind == identExpr:
var c = IdentExpr(c)
var constant = IdentExpr(constant)
if c.name.lexeme == constant.name.lexeme:
return i
else:
continue
self.consts.add(constant)
result = self.consts.high()

View File

@ -1,4 +1,4 @@
# Copyright 2021 Mattia Giambirtone & All Contributors
# Copyright 2022 Mattia Giambirtone & All Contributors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.

View File

@ -1,4 +1,4 @@
# Copyright 2021 Mattia Giambirtone & All Contributors
# Copyright 2022 Mattia Giambirtone & All Contributors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.

View File

@ -1,4 +1,4 @@
# Copyright 2021 Mattia Giambirtone & All Contributors
# Copyright 2022 Mattia Giambirtone & All Contributors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.

View File

@ -1,4 +1,4 @@
# Copyright 2021 Mattia Giambirtone & All Contributors
# Copyright 2022 Mattia Giambirtone & All Contributors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.

View File

@ -1,4 +1,4 @@
# Copyright 2021 Mattia Giambirtone & All Contributors
# Copyright 2022 Mattia Giambirtone & All Contributors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.

View File

@ -1,4 +1,4 @@
# Copyright 2021 Mattia Giambirtone & All Contributors
# Copyright 2022 Mattia Giambirtone & All Contributors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.

View File

@ -1,4 +1,4 @@
# Copyright 2021 Mattia Giambirtone
# Copyright 2022 Mattia Giambirtone
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.

View File

@ -1,4 +1,4 @@
# Copyright 2021 Mattia Giambirtone & All Contributors
# Copyright 2022 Mattia Giambirtone & All Contributors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.

View File

@ -1,4 +1,4 @@
# Copyright 2021 Mattia Giambirtone & All Contributors
# Copyright 2022 Mattia Giambirtone & All Contributors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.