Skip to content
This repository has been archived by the owner on Dec 11, 2022. It is now read-only.

Commit

Permalink
Merge pull request #97 from Skiylia-Lang/develop
Browse files Browse the repository at this point in the history
Variable reassignment fixed
  • Loading branch information
mergify[bot] authored Jul 5, 2021
2 parents 8071616 + 1198ce6 commit 5320c62
Show file tree
Hide file tree
Showing 7 changed files with 107 additions and 52 deletions.
8 changes: 8 additions & 0 deletions ExampleCode/Assignment/Variables/Implicit_Declaration.skiy
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
//explicitly declare a variable
a = 2

print(a)

b = "hello world"

print(b)
7 changes: 6 additions & 1 deletion ExampleCode/ControlFlow/ForArray.skiy
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
//loop through the contents of an array object

var a = array("one", "two", "three", "four", "five", "six")

for x in a:
print(x)


//or do so implicitly

for x in array("one", "two", "three", "four", "five", "six"):
print(x)
5 changes: 3 additions & 2 deletions ExampleCode/Grammar/ExtendedBakusNaurForm.txt
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ function > Identifier "(" parameters? ")" {Block token} block

parameters > Identifier ( "," Identifier )*

vardeclaration > ("var" Idenitifer ( "=" expression )? ) "\n"+ <=explicit requires "var"
vardeclaration > ("var"? Idenitifer ( "=" expression )? ) "\n"+ <=explicit requires "var"

statement > checkstmt | dostmt | exprstmt | forstmt | ifstmt | interuptstmt | returnstmt | untilstmt | whilestmt | block

Expand All @@ -53,7 +53,8 @@ exprstmt > expression {End token}+

forstmt > "for" (vardeclaration | exprstmt) (("when" | "where") expression)? ("do" expression)? {Block token} statement
| "for" (vardeclaration | exprstmt) "in" Identifier
//allowed for loop types 1) for x: 2) for x when x<=10: 3) for x when x<10 do x=x+2: 4) for x do x=x+2:
//allowed for loop types 1) for x: 2) for x when x<=10: 3) for x when x<10 do x=x+2:
4) for x do x=x+2: 5) for x in array(1, 2, 3):

ifstmt > "if" expression {Block token} statement ( ("elif" | "else if") expression {Block token} statement )* ("else" statement)?

Expand Down
15 changes: 8 additions & 7 deletions ExampleCode/Grammar/FullGrammar.skiy
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,9 @@ a ?: b //if a is true, then a, else b <-elvis operator, equivalent to a
a ?? b //if a null, then b, else a <-null coalescence operator, equivalent to a!=null ? a : b, but does not evaluate 'a' twice

//Variables and assignment
var a //initialise as 0
a = 5 //reassign a as 5. a must already exist
var a //initialise as 0.
a = 5 //reassign a as 5.
b = 3 //implicitly define b as 3
check a //evaluates the truthiness of a, thorwing an error if it is false

//control flow
Expand Down Expand Up @@ -144,15 +145,15 @@ for x (Where | When) x<10 do x=x+2
print(x)
//explicitly defining the increment operation

for x in 10:
print(x)
//implicitly define '(Where | When) x<10' as 'in 10' <-- NOT SURE IF I WANT TO KEEP THIS BEHAVIOUR

for x do x=x+2:
print(x)
//basically a while loop with a defined increment and implicitly declared variable

for x in Array(1, 2, 3, 4, 5):
/// for x in 10:
print(x)
//implicitly define '(Where | When) x<10' as 'in 10' <-- BEHAVIOUR REMOVED IN PYSKIYLIA 0.8.2

for x in array(1, 2, 3, 4, 5):
print(x)
//loops through the array-like, technically an implicit conditional and incremental

Expand Down
2 changes: 1 addition & 1 deletion PySkiylia/Interpreter.py
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,7 @@ def AssignExpr(self, expr):
self.environment.assignAt(dist, expr.name.lexeme, value)
else:
#otherwise, add to globals
self.globals.define(expr.name, value)
self.globals.define(expr.name.lexeme, value)
return value

#define a way of unpacking a binary expression
Expand Down
118 changes: 81 additions & 37 deletions PySkiylia/Parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ def __init__(self, skiylia, tokens=[], primitives=[], workingdir="", imported=[]
self.primitives = primitives
#define all of the tokens that can start a block (not a lot as of current)
self.blockStart = ["Colon"]
#define the variables that have been created in this parser
self.non_user_vars, self.vars = 0, set()
#define the current directory
self.mydir = workingdir
#and define a list of imported modules
Expand Down Expand Up @@ -184,12 +186,9 @@ def checkstatement(self):
#define the do statement grammar
def dostatement(self):
#fetch the loop
print("do statement")
if self.match("While"):
print("while")
loop = self.whilestatement()
elif self.match("Until"):
print("until")
loop = self.untilstatement()
else:
#ensure we don't have a floating
Expand Down Expand Up @@ -256,36 +255,49 @@ def forstatement(self):

#check if we have been given an itteration expression
if self.match("In"):
#fetch the itterable object
itt = self.expression().name
#construct an array index variable
self.tokens.insert(self.current, Tokens.Token("End", "", None, itt.line, itt.char, itt.indent))
self.tokens.insert(self.current, Tokens.Token("Identifier", "__idx__", None, itt.line, itt.char, itt.indent))
init = self.varDeclaration()
#fetch the "in" token
itk, itk_num = self.previous(), self.current
#fetch the itterable
itt = self.expression()
#ensure we have a variable, and this is slightly easier
if hasattr(itt, "name"):
pass
#else, check if we have a raw array
elif hasattr(itt, "callee") and ((itt.callee.name.lexeme == "array") or (itt.callee.name.lexeme == "arr")):
self.insertToken("End")
self.current = itk_num
self.insertToken("Equal", "=")
self.insertToken("Identifier", "__arr{}__".format(self.non_user_vars))
itt = self.varDeclaration()
self.stmt.append(itt)
#otherwise, throw an error
else:
raise SyntaxError(self.error(itk, "Non itterable object"))
#create an index variable that holds our position in the array, and add it to the loop, __idx__ = 0
init = self.constructvariable()
self.stmt.append(init)
#construct an index increment
self.constructincremental(init.name)
increment = self.expression()
#construct 'x < itterable.len()'
self.tokens.insert(self.current, Tokens.Token("RightParenthesis", ")", None, itt.line, itt.char, itt.indent))
self.tokens.insert(self.current, Tokens.Token("LeftParenthesis", "(", None, itt.line, itt.char, itt.indent))
self.tokens.insert(self.current, Tokens.Token("Identifier", "len", None, itt.line, itt.char, itt.indent))
self.tokens.insert(self.current, Tokens.Token("Dot", ".", None, itt.line, itt.char, itt.indent))
self.tokens.insert(self.current, itt)
self.tokens.insert(self.current, Tokens.Token("Less", "<", None, itt.line, itt.char, itt.indent))
self.tokens.insert(self.current, init.name)
# fetch the constructed condition
#construct the index incremental, __idx__++
increment = self.constructincremental(init.name)
#construct the conditional, __idx__ < array.len()
self.insertToken("RightParenthesis", ")")
self.insertToken("LeftParenthesis", "(")
self.insertToken("Identifier", "len")
self.insertToken("Dot", ".")
self.insertToken(itt.name)
self.insertToken("Less", "<")
self.insertToken(init.name)
condition = self.expression()
#and finally, construct the expression that sets the 'incremental' to each array value
self.tokens.insert(self.current+1, Tokens.Token("End", "", None, itt.line, itt.char, itt.indent + 1))
self.tokens.insert(self.current+1, Tokens.Token("RightParenthesis", ")", None, itt.line, itt.char, itt.indent + 1))
self.tokens.insert(self.current+1, init.name)
self.tokens.insert(self.current+1, Tokens.Token("LeftParenthesis", "(", None, itt.line, itt.char, itt.indent + 1))
self.tokens.insert(self.current+1, Tokens.Token("Identifier", "get", None, itt.line, itt.char, itt.indent + 1))
self.tokens.insert(self.current+1, Tokens.Token("Dot", ".", None, itt.line, itt.char, itt.indent + 1))
self.tokens.insert(self.current+1, itt)
self.tokens.insert(self.current+1, Tokens.Token("Equal", "=", None, itt.line, itt.char, itt.indent + 1))
self.tokens.insert(self.current+1, initialiser.name)
#construct the incremental association, x = b.get(__idx__)
self.current+=1
self.insertToken("RightParenthesis", ")")
self.insertToken(init.name)
self.insertToken("LeftParenthesis", "(")
self.insertToken("Identifier", "get")
self.insertToken("Dot", ".")
self.insertToken(itt.name)
self.insertToken("Equal", "=")
self.insertToken(initialiser.name)
self.current-=1
#otherwise, fetch the conditional / increment
else:
#check it has not been ommited
Expand All @@ -296,8 +308,7 @@ def forstatement(self):
if self.match("Do"):
increment = self.expression()
else:
self.constructincremental(initialiser.name)
increment = self.expression()
increment = self.constructincremental(initialiser.name)

#check for the colon grammar
if not self.check(*self.blockStart):
Expand Down Expand Up @@ -461,6 +472,8 @@ def varDeclaration(self, *Endings):
initial = self.expression()
#make sure the variable is bounded
self.consume("Unbounded variable declaration.", *Endings)
#add the variable to our set
self.vars.add(name.lexeme)
#return the variable abstraction
return Var(name, initial)

Expand Down Expand Up @@ -525,7 +538,12 @@ def assignment(self):
#if it is a Variable type
if isinstance(expr, Variable):
name = expr.name
#return the assignment
#check if this has been used before
if name.lexeme not in self.vars:
#add to our set
self.vars.add(name.lexeme)
return Var(name, value)
#otherwise, return the assignment
return Assign(name, value)
elif isinstance(expr, Get):
return Set(expr.object, expr.name, value)
Expand Down Expand Up @@ -755,9 +773,35 @@ def checkError(self):
#and return true, as we found an error
return True

def constructincremental(self, var):
self.tokens.insert(self.current, Tokens.Token("PPlus", "++", None, var.line, var.char, var.indent))
self.tokens.insert(self.current, var)
#function to very quickly insert a token a the current position
def insertToken(self, ttype, lexeme="", literal=None, line=0, char=0, indent=0):
if isinstance(ttype, str):
self.tokens.insert(self.current, Tokens.Token(ttype, lexeme, literal, line, char, indent))
else:
self.tokens.insert(self.current, ttype)

#very quickly construct and insert a variable definition
def constructvariable(self, varname="____", value=None):
self.insertToken("End", "")
if value is not None:
if isinstance(value, str):
self.insertToken("Identifier", value, value)
elif isinstance(value, (float, int)):
self.insertToken("Number", value, value)
self.insertToken("Equal", "=")
if varname == "____":
self.insertToken("Identifier", "__var{}__".format(self.non_user_vars))
self.non_user_vars += 1
return self.varDeclaration()

#very quickly construct and insert an incremental token stream
def constructincremental(self, var, positive = True):
if positive:
self.insertToken("PPlus", "++")
else:
self.insertToken("MMinus", "--")
self.insertToken(var)
return self.expression()

#define a way of checking if a token is found, and consuming it
def consume(self, errorMessage, *tokentypes, silentError=False):
Expand Down
4 changes: 0 additions & 4 deletions PySkiylia/SkiyliaCallable.py
Original file line number Diff line number Diff line change
Expand Up @@ -151,10 +151,6 @@ def newcall(interpreter, arguments, token=""):
#and return the callable
return a

#array shorthand
class SkiyliaArr(SkiyliaArray):
callname = "Arr"

#internal handling of functions
class SkiyliaFunction(SkiyliaCallable):
string = "Skiylia function"
Expand Down

0 comments on commit 5320c62

Please sign in to comment.