-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Paving the way for the dynamic value system.
- Loading branch information
Showing
17 changed files
with
937 additions
and
19 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -25,4 +25,5 @@ Graphics | |
drawSurfaceScaled | ||
drawSurfaceRotated | ||
TermCanvas | ||
getRedirect | ||
getRedirect | ||
|
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
|
||
-- @once | ||
|
||
-- @ifndef __INCLUDE_sheets | ||
-- @error 'sheets' must be included before including 'sheets.dynamic.BinaryExpression' | ||
-- @endif | ||
|
||
-- @print Including sheets.dynamic.BinaryExpression | ||
|
||
local tostring = { | ||
[OPERATOR_BINARY_ADD] = "+"; | ||
[OPERATOR_BINARY_SUB] = "-"; | ||
[OPERATOR_BINARY_MUL] = "*"; | ||
[OPERATOR_BINARY_DIV] = "/"; | ||
[OPERATOR_BINARY_MOD] = "%"; | ||
[OPERATOR_BINARY_POW] = "^"; | ||
} | ||
|
||
class "BinaryExpression" extends "Expression" { | ||
lvalue = nil; | ||
operator = nil; | ||
rvalue = nil; | ||
} | ||
|
||
function BinaryExpression:BinaryExpression( position, lvalue, operator, rvalue ) | ||
parameters.checkConstructor( self.class, 4, "position", TokenPosition, position, "lvalue", Expression, lvalue, "operator", "number", operator, "rvalue", Expression, rvalue ) | ||
|
||
self.position = position | ||
self.lvalue = lvalue | ||
self.operator = operator | ||
self.rvalue = rvalue | ||
end | ||
|
||
function BinaryExpression:resolve( env ) | ||
local lvalue, rvalue = self.lvalue:resolve( env ), self.rvalue:resolve( env ) | ||
|
||
if type( lvalue ) ~= "number" then | ||
Exception.throw( ParserException( "expected number lvalue, got " .. type( lvalue ), self.position ) ) | ||
elseif type( rvalue ) ~= "number" then | ||
Exception.throw( ParserException( "expected string rvalue, got " .. type( rvalue ), self.position ) ) | ||
end | ||
|
||
if self.operator == OPERATOR_BINARY_ADD then | ||
return lvalue + rvalue | ||
elseif self.operator == OPERATOR_BINARY_SUB then | ||
return lvalue - rvalue | ||
elseif self.operator == OPERATOR_BINARY_MUL then | ||
return lvalue * rvalue | ||
elseif self.operator == OPERATOR_BINARY_DIV then | ||
return lvalue / rvalue | ||
elseif self.operator == OPERATOR_BINARY_MOD then | ||
return lvalue % rvalue | ||
elseif self.operator == OPERATOR_BINARY_POW then | ||
return lvalue ^ rvalue | ||
end | ||
end | ||
|
||
function BinaryExpression:substitute( env ) | ||
self.lvalue:substitute( env ) | ||
self.rvalue:substitute( env ) | ||
end | ||
|
||
function BinaryExpression:isConstant() | ||
return self.lvalue:isConstant() and self.rvalue:isConstant() | ||
end | ||
|
||
function BinaryExpression:tostring() | ||
return "(" .. self.lvalue:tostring() .. ")" .. tostring[self.operator] .. "(" .. self.rvalue:tostring() .. ")" | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
|
||
-- @once | ||
|
||
-- @ifndef __INCLUDE_sheets | ||
-- @error 'sheets' must be included before including 'sheets.dynamic.ConstantExpression' | ||
-- @endif | ||
|
||
-- @print Including sheets.dynamic.ConstantExpression | ||
|
||
class "ConstantExpression" extends "Expression" { | ||
value = 0; | ||
} | ||
|
||
function ConstantExpression:ConstantExpression( position, value ) | ||
parameters.checkConstructor( self.class, 1, "position", TokenPosition, position ) | ||
self.value = value | ||
self.position = position | ||
end | ||
|
||
function ConstantExpression:resolve( env ) | ||
return self.value | ||
end | ||
|
||
function ConstantExpression:isConstant() | ||
return true | ||
end | ||
|
||
function ConstantExpression:tostring() | ||
return tostring( self.value ) | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
|
||
-- @once | ||
|
||
-- @ifndef __INCLUDE_sheets | ||
-- @error 'sheets' must be included before including 'sheets.dynamic.Expression' | ||
-- @endif | ||
|
||
-- @print Including sheets.dynamic.Expression | ||
|
||
class "Expression" { | ||
position = nil; | ||
} | ||
|
||
function Expression:Expression( position ) | ||
self.position = position | ||
end | ||
|
||
function Expression:resolve( env ) | ||
|
||
end | ||
|
||
function Expression:substitute( env ) | ||
|
||
end | ||
|
||
function Expression:isConstant() | ||
|
||
end | ||
|
||
function Expression:tostring() | ||
|
||
end | ||
|
||
function Expression:throw( err ) | ||
return Exception.throw( ExpressionException( self.position:tostring() .. ": " .. tostring( err ), 0 ) ) | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
|
||
-- @once | ||
|
||
-- @ifndef __INCLUDE_sheets | ||
-- @error 'sheets' must be included before including 'sheets.dynamic.ExpressionEnvironment' | ||
-- @endif | ||
|
||
-- @print Including sheets.dynamic.ExpressionEnvironment | ||
|
||
class "ExpressionEnvironment" { | ||
environment = {}; | ||
} | ||
|
||
function ExpressionEnvironment:ExpressionEnvironment() | ||
self.environment = {} | ||
end | ||
|
||
function ExpressionEnvironment:set( index, value ) | ||
self.environment[index] = value | ||
return self | ||
end | ||
|
||
function ExpressionEnvironment:get( index ) | ||
return self.environment[index] | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,176 @@ | ||
|
||
-- @once | ||
|
||
-- @ifndef __INCLUDE_sheets | ||
-- @error 'sheets' must be included before including 'sheets.dynamic.ExpressionParser' | ||
-- @endif | ||
|
||
-- @print Including sheets.dynamic.ExpressionParser | ||
|
||
local operators = { | ||
["+"] = true; | ||
["-"] = OPERATOR_UNARY_MINUS; | ||
["*"] = true; | ||
["/"] = true; | ||
["%"] = true; | ||
["^"] = true; | ||
["#"] = OPERATOR_UNARY_LEN; | ||
["!"] = OPERATOR_UNARY_NOT; | ||
} | ||
|
||
local binary_operators = { | ||
["+"] = OPERATOR_BINARY_ADD; | ||
["-"] = OPERATOR_BINARY_SUB; | ||
["*"] = OPERATOR_BINARY_MUL; | ||
["/"] = OPERATOR_BINARY_DIV; | ||
["%"] = OPERATOR_BINARY_MOD; | ||
["^"] = OPERATOR_BINARY_POW; | ||
} | ||
|
||
local precedence = { | ||
["+"] = 0; | ||
["-"] = 0; | ||
["*"] = 1; | ||
["/"] = 1; | ||
["%"] = 1; | ||
["^"] = 2; | ||
} | ||
|
||
class "ExpressionParser" extends "Parser" { | ||
token = 1; | ||
} | ||
|
||
function ExpressionParser:consume() | ||
if self:finished() then | ||
return Token( TOKEN_EOF, nil, self.position ) | ||
end | ||
|
||
if self:matchString() then | ||
return self:consumeString() | ||
elseif self:matchNumber() then | ||
return self:consumeNumber() | ||
elseif self:matchIdentifier() then | ||
return self:consumeIdentifier() | ||
elseif self:matchWhitespace() then | ||
return self:consumeWhitespace() | ||
else | ||
self.character = self.character + 1 | ||
if operators[self.text:sub( self.character - 1, self.character - 1 )] then | ||
return Token( TOKEN_OPERATOR, self.text:sub( self.character - 1, self.character - 1 ), self:advancePosition( 1 ) ) | ||
end | ||
return Token( TOKEN_SYMBOL, self.text:sub( self.character - 1, self.character - 1 ), self:advancePosition( 1 ) ) | ||
end | ||
end | ||
|
||
function ExpressionParser:peek( n ) | ||
return self.tokens[self.token + ( n or 0 )] or Token( TOKEN_EOF, nil, self.position ) | ||
end | ||
|
||
function ExpressionParser:next() | ||
self.token = self.token + 1 | ||
return self:peek( -1 ) | ||
end | ||
|
||
function ExpressionParser:test( ... ) | ||
return self:peek():matches( ... ) | ||
end | ||
|
||
function ExpressionParser:parseUnaryLeftOperator() | ||
if self:test( TOKEN_OPERATOR, "-" ) or self:test( TOKEN_OPERATOR, "#" ) or self:test( TOKEN_OPERATOR, "!" ) then | ||
return self:next() | ||
end | ||
end | ||
|
||
function ExpressionParser:parseUnaryRightOperator( lvalue ) | ||
if self:test( TOKEN_SYMBOL, "(" ) then | ||
-- stuff | ||
elseif self:test( TOKEN_SYMBOL, "." ) then | ||
-- stuff | ||
end | ||
return lvalue | ||
end | ||
|
||
function ExpressionParser:parseAtom() | ||
if self:test( TOKEN_STRING ) or self:test( TOKEN_INT ) or self:test( TOKEN_FLOAT ) then | ||
return ConstantExpression( self:peek().position, self:next().value ) | ||
elseif self:test( TOKEN_IDENT ) then | ||
return IdentifierExpression( self:peek().position, self:next().value ) | ||
else | ||
Exception.throw( ParserException( "expected constant or identifier, got " .. self:peek().token, self:peek().position ) ) | ||
end | ||
end | ||
|
||
function ExpressionParser:parseNode() | ||
local lops = {} | ||
local node | ||
while true do | ||
local lop = self:parseUnaryLeftOperator() | ||
if lop then | ||
lops[#lops + 1] = lop | ||
else | ||
break | ||
end | ||
end | ||
|
||
node = self:parseAtom() | ||
|
||
while true do | ||
local rop = self:parseUnaryRightOperator( node ) | ||
if rop ~= node then | ||
node = rop | ||
else | ||
break | ||
end | ||
end | ||
|
||
for i = #lops, 1, -1 do | ||
node = UnaryLeftExpression( lops[i].position, operators[lops[i].value], node ) | ||
end | ||
|
||
return node | ||
end | ||
|
||
function ExpressionParser:parseBinaryOperator( lvalue ) | ||
local operator = self:peek().value | ||
local position = self:next().position | ||
local p = precedence[operator] | ||
local rvalue = self:parseNode() | ||
|
||
while true do | ||
if self:test( TOKEN_OPERATOR ) then | ||
local op = self:peek().value | ||
position = self:peek().position | ||
|
||
if not precedence[op] then | ||
Exception.throw( ParserException( "expected binary operator, got " .. self:peek().token, self:peek().position ) ) | ||
end | ||
|
||
if precedence[op] > p then | ||
rvalue = self:parseBinaryOperator( rvalue ) | ||
elseif precedence[op] == p then | ||
return self:parseBinaryOperator( BinaryExpression( position, lvalue, binary_operators[operator], rvalue ) ) | ||
else | ||
return BinaryExpression( position, lvalue, binary_operators[operator], rvalue ) | ||
end | ||
else | ||
return BinaryExpression( position, lvalue, binary_operators[operator], rvalue ) | ||
end | ||
end | ||
end | ||
|
||
function ExpressionParser:parseExpression() | ||
local lvalue = self:parseNode() | ||
|
||
while self:test( TOKEN_OPERATOR ) do | ||
if precedence[self:peek().value] then | ||
lvalue = self:parseBinaryOperator( lvalue ) | ||
else | ||
Exception.throw( ParserException( "expected binary operator, got " .. self:peek().token, self:peek().position ) ) | ||
end | ||
end | ||
if not self:test( TOKEN_EOF ) then | ||
Exception.throw( ParserException( "unexpected " .. self:peek().token, self:peek().position ) ) | ||
end | ||
|
||
return lvalue | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
|
||
-- @once | ||
|
||
-- @ifndef __INCLUDE_sheets | ||
-- @error 'sheets' must be included before including 'sheets.dynamic.IdentifierExpression' | ||
-- @endif | ||
|
||
-- @print Including sheets.dynamic.IdentifierExpression | ||
|
||
class "IdentifierExpression" extends "Expression" { | ||
name = ""; | ||
const_value = nil; | ||
} | ||
|
||
function IdentifierExpression:IdentifierExpression( position, name ) | ||
parameters.checkConstructor( self.class, 2, "position", TokenPosition, position, "name", "string", name ) | ||
|
||
self.name = name | ||
self.position = position | ||
end | ||
|
||
function IdentifierExpression:resolve( env ) | ||
return self.const_value or env:get( self.name ) | ||
end | ||
|
||
function IdentifierExpression:substitute( env ) | ||
self.const_value = env:get( self.name ) | ||
end | ||
|
||
function IdentifierExpression:isConstant() | ||
return self.const_value ~= nil | ||
end | ||
|
||
function IdentifierExpression:tostring() | ||
return self.name | ||
end |
Oops, something went wrong.