From e2bbbfe1611f12b33692af175d661fa25b2cc616 Mon Sep 17 00:00:00 2001 From: Bruce Hill Date: Fri, 29 Sep 2017 22:04:03 -0700 Subject: [PATCH] More stuff is working more better. --- examples/sample_game.nom | 138 +++++++++++++++++++-------------------- lib/control_flow.nom | 14 ++-- lib/metaprogramming.nom | 7 +- lib/operators.nom | 10 +-- lib/permissions.nom | 17 +++-- lib/plurals.nom | 10 +-- lib/secrets.nom | 11 +--- nomsu.lua | 3 +- nomsu.moon | 3 +- 9 files changed, 104 insertions(+), 109 deletions(-) diff --git a/examples/sample_game.nom b/examples/sample_game.nom index 15d86f9..3f9d6bc 100644 --- a/examples/sample_game.nom +++ b/examples/sample_game.nom @@ -3,7 +3,6 @@ require "lib/permissions.nom" require "lib/secrets.nom" require "lib/plurals.nom" - # Users: with secrets: secret %users =: lua expr ".." @@ -11,18 +10,14 @@ with secrets: | {by_name=function(self, key) return "User<"..key..">" end, | add=function(self, key) self[key] = self:by_name(key) end} |}) - rule [find user %name] =: + rule (find user %name; @%name) =: lua expr "secrets.users:by_name(vars.name) or nomsu:error('Failed to find user: '..tostring(vars.name))" - rule [add user %name] =: + rule (add user %name) =: lua expr "secrets.users:add(vars.name)" - macro [@%name_block] =: - %name_str =: lua expr "vars.name_block.value.value.src" - ".." - |nomsu:call("find user %", \repr %name_str\) - rule [everybody, everyone] =: + rule (everybody; everyone) =: (%entry's "key") for %entry in (entries in (secret %users)) - rule [rules that change users] =: ["add user %"] + rule (rules that change users) =: ["add user %"] # Inventory: with secrets: @@ -33,57 +28,55 @@ with secrets: | return t |end}) - rule [inventory] =: - dict (..) - [%inv's "key", dict (%entry for %entry in (entries in (%inv's "value")))] - ..for %inv in (entries in (secret %inventory)) + rule (inventory) =: dict: + [%inv's "key", dict (%entry for %entry in (entries in (%inv's "value")))] + ..for %inv in (entries in (secret %inventory)) - rule [%person's inventory] =: + rule (%person's inventory) =: dict (%entry for %entry in (entries in ((secret %inventory)->%person))) - rule [%person's stock of %item] =: + rule (%person's stock of %item) =: %item =: canonicalize %item ((%person's inventory)->%item) or 0 - rule [%person's stock of %item as str] =: + rule (%person's stock of %item as str) =: %item =: canonicalize %item %count =: %person's stock of %item ".." - |\%count\ \(singular %item) if (%count == 1) else (plural %item)\ + |\(%count) \((singular %item) if (%count == 1) else (plural %item)) - rule [give %person %count %item] =: + rule (give %person %count %item) =: %item =: canonicalize %item (%person's inventory)-> %item =: (%person's stock of %item) + %count - rule [give %person %count %item from %donor] =: + rule (give %person %count %item from %donor) =: %item =: canonicalize %item if ((%donor's stock of %item) < %count): say ".." - |\%donor\ does not have enough \%item\ to transfer + |\(%donor) does not have enough \(%item) to transfer ..else: (%person's inventory)->%item =: (%person's stock of %item) + %count (%donor's inventory)->%item =: (%donor's stock of %item) - %count - rule [%person has %item, %person has a %item, %person has an %item] =: + rule (%person has %item; %person has a %item; %person has an %item) =: (%person's stock of %item) > 0 - rule [rules that change the inventory] =: [..] + rule (rules that change the inventory) =: [..] "give % % %", "give % % % from %" - rule [rules that view the inventory] =: [..] + rule (rules that view the inventory) =: [..] "inventory", "%'s inventory", "%'s stock of %", "%'s stock of % as str" -rule [you] =: +rule (you) =: lua expr "(nomsu.you or 'Anonymous')" -rule [make %person %action, make %person do %action] =: - lua block ".." - |do - | local old_you = nomsu.you - | nomsu.you = vars.person - | ret = vars.action(nomsu, vars) - | nomsu.you = old_you - |end +rule (make %person %action; make %person do %action) =: + lua code ".." + |local old_you = nomsu.you + |nomsu.you = vars.person + do %action + lua code ".." + |nomsu.you = old_you say "====================================================" say " NEW GAME" @@ -91,27 +84,26 @@ say "====================================================" # Unanimity for proposals with secrets: - rule [pending proposal] =: + rule (pending proposal) =: secret %pending - rule [propose source %src] =: + rule (propose source %src) =: if (secret %pending): error "A proposal is already pending." secret %pending =: %src secret %approvals =: [] say ".." |Proposal: - |\%src\ + |\(%src) - macro block [propose %action] =: - %source =: source code from tree %action - ".." - |nomsu:call("propose source %", \repr %source\) + parse (propose %action) as: + propose source: + source code from tree \%action - rule [with everyone's approval do %action] =: + rule (with everyone's approval do %action) =: run %action - rule [mark %who as approving] =: + rule (mark %who as approving) =: if (not (pending proposal)): say "No action pending" return @@ -128,32 +120,31 @@ with secrets: secret %pending =: nil secret %approvals =: nil - rule [mark %who as rejecting] =: + rule (mark %who as rejecting) =: secret %pending =: nil secret %approvals =: nil - rule [approve, vote yes, vote yea] =: + rule (approve; vote yes; vote yea) =: mark (you) as approving - rule [reject, vote no, vote nay, veto, disapprove] =: + rule (reject; vote no; vote nay; veto; disapprove) =: mark (you) as rejecting restrict "with everyone's approval do %" to within "mark % as approving" restrict "mark % as approving" to within "approve" restrict "mark % as rejecting" to within "reject" -rule [join] =: +rule (join) =: add user (you) say ".." - |Welcome to the game, \you\! + |Welcome to the game, \(you)! restrict (rules that change users) to within "join" -restrict (..) - flatten [..] - ["rule % = %", "make % %", "restrict % to within %"] - (rules that change the inventory) +restrict: flatten [..] + ["rule % = %", "make % %", "restrict % to within %"] + (rules that change the inventory) ..to within "with everyone's approval do %" say "Rule making is now restricted" @@ -176,7 +167,7 @@ propose: approve propose: - rule [fart] =: + rule (fart) =: say "poot" say "fart should have been defined" approve @@ -185,7 +176,7 @@ fart propose: with secrets: - rule [open election %candidates %action] =: + rule (open election %candidates %action) =: if (secret %candidates): error "An election is already in progress." ..else: @@ -194,82 +185,85 @@ propose: secret %action =: %action secret %winner =: nil - rule [close the election] =: + rule (close the election) =: secret %candidates =: nil secret %votes =: nil secret %action =: nil secret %winner =: nil - rule [votes for %candidate] =: + rule (votes for %candidate) =: %votes =: [] for %entry in (entries in (secret %votes)): if ((%entry's "value") == %candidate): add (%entry's "key") to %votes %votes - rule [after winning a fair election do %action] =: + rule (after winning a fair election do %action) =: do %action - rule [the winner] =: secret %winner + rule (the winner) =: secret %winner - rule [vote for %candidate] =: + rule (vote for %candidate) =: for %c in (secret %candidates): if (%c == %candidate): go to %candidate-is-legit error ".." - |Invalid candidate: \%candidate\ + |Invalid candidate: \(%candidate) -> %candidate-is-legit (secret %votes)->(you) =: %candidate %vote-percent =: (number of (votes for %candidate)) / (number of (everyone)) say ".." - |Vote cast. \%candidate\ now has \100 * %vote-percent\% of the votes. + |Vote cast. \(%candidate) now has \(100 * %vote-percent)% of the votes. if (%vote-percent > 0.5): secret %winner =: %candidate after winning a fair election do (secret %action) close the election - rule [rules that change the election] =: [..] + rule (rules that change the election) =: [..] "open election %", "close the election", "vote for %" - rule [rules that view the election] =: [..] + rule (rules that view the election) =: [..] "votes for %" approve propose: - rule [as bill %action] =: + rule (_as bill %action) =: if ((you) == "Anonymous"): make "bill" do %action ..else: say ".." - |Who do you think you are, \you\? - allow ["as bill %"] to use ["make % %"] + |Who do you think you are, \(you)? + parse (as bill %) as (_as bill \%) + allow ["_as bill %"] to use ["make % %"] approve as bill: join propose: - rule [as dave %action] =: + rule (_as dave %action) =: if ((you) == "Anonymous"): make "dave" do %action ..else: say ".." - |Who do you think you are, \you\? - allow ["as dave %"] to use ["make % %"] + |Who do you think you are, \(you)? + parse (as dave %) as (_as dave \%) + allow ["_as dave %"] to use ["make % %"] approve as bill: approve as dave: join propose: - rule [declare war] =: say "WAR!!!" + rule (declare war) =: say "WAR!!!" with secrets: secret %president =: nil - rule [elect president from %candidates] =: + rule (elect president from %candidates) =: open election %candidates: - say ".."|Hail to the chief: \the winner\ + say ".." + |Hail to the chief: \(the winner) secret %president =: the winner - rule [as the president do %action] =: do %action + rule (as the president do %action) =: do %action restrict "declare war" to within "as the president do %" approve @@ -284,7 +278,7 @@ as dave: declare war propose: - rule [take a shit] =: say "shit taken." + rule (take a shit) =: say "shit taken." approve as bill: approve diff --git a/lib/control_flow.nom b/lib/control_flow.nom index 4e13a8c..2ff764d 100644 --- a/lib/control_flow.nom +++ b/lib/control_flow.nom @@ -40,7 +40,7 @@ compile (continue %var; go to next %var; on to the next %var) to code: ".." # While loops compile (repeat while %condition %body) to block: ".." - |while \(%condition) do + |while \(%condition as lua) do | \(%body as lua statements) | ::continue_repeat:: |end @@ -87,8 +87,7 @@ parse (for all %iterable %body) as: for % in %iterable %body compile (when %body) to block: %result =: "" %fallthroughs =: [] - for %statement in (%body's "value"): - %func-call =: %statement's "value" + for %func-call in (%body's "value"): assert ((%func-call's "type") == "FunctionCall") ".." |Invalid format for 'when' statement. Only '*' blocks are allowed. %tokens =: %func-call's "value" @@ -103,7 +102,7 @@ compile (when %body) to block: %action =: %tokens -> 3 if (%action == (nil)): lua block "table.insert(vars.fallthroughs, vars.condition)" - go to next %statement + go to next %func-call if (lua expr "vars.condition.type == 'Word' and vars.condition.value == 'else'"): %result join=: ".." @@ -129,10 +128,9 @@ compile (when %body) to block: # Switch statement compile (when %branch-value == ? %body) to block: - %result =: "local branch_value = \(%branch-value)" + %result =: "local branch_value = \(%branch-value as lua)" %fallthroughs =: [] - for %statement in (%body's "value"): - %func-call =: %statement's "value" + for %func-call in (%body's "value"): assert ((%func-call's "type") == "FunctionCall") ".." |Invalid format for 'when' statement. Only '*' blocks are allowed. %tokens =: %func-call's "value" @@ -147,7 +145,7 @@ compile (when %branch-value == ? %body) to block: %action =: %tokens -> 3 if (%action == (nil)): lua block "table.insert(vars.fallthroughs, vars.condition)" - go to next %statement + go to next %func-call if (lua expr "vars.condition.type == 'Word' and vars.condition.value == 'else'"): %result join=: ".." diff --git a/lib/metaprogramming.nom b/lib/metaprogramming.nom index a12cfc6..4aa10e3 100644 --- a/lib/metaprogramming.nom +++ b/lib/metaprogramming.nom @@ -13,7 +13,7 @@ lua code ".." |nomsu:def(%s, %s, %s) |]]):format(nomsu:repr(canonical.src), thunk, nomsu:repr(body.src)) | if #aliases > 1 then - | lua = lua .. ([[ + | lua = lua .. "\n" .. ([[ |do | local aliased = %s | local src = %s @@ -27,8 +27,7 @@ lua code ".." |]]):format(nomsu:repr(aliases[i].src), nomsu:repr(canonical.src)) | end | lua = lua .. [[ - |end - |]] + |end]] | end | return nil, lua |end, "") @@ -72,6 +71,8 @@ parse (compile %macro_def to block %body) as: escaped compile \%macro_def to cod | \(%body) |end +rule (do %) =: % + rule (%tree as lua) =: lua expr "nomsu:tree_to_lua(\(%tree))" rule (%tree as value) =: diff --git a/lib/operators.nom b/lib/operators.nom index 4d81806..7a926f3 100644 --- a/lib/operators.nom +++ b/lib/operators.nom @@ -29,11 +29,11 @@ compile (%obj's %key; %obj -> %key) to: "\(%obj as lua)[\(%key as lua)]" # Variable assignment operator, and += type versions compile (%var = %val) to code: "\(%var as lua) = \(%val as lua)" -compile (%var += %val) to code: "\(%var as lua) += \(%val as lua)" -compile (%var -= %val) to code: "\(%var as lua) -= \(%val as lua)" -compile (%var *= %val) to code: "\(%var as lua) *= \(%val as lua)" -compile (%var /= %val) to code: "\(%var as lua) /= \(%val as lua)" -compile (%var ^= %val) to code: "\(%var as lua) ^= \(%val as lua)" +compile (%var += %val) to code: "\(%var as lua) = \(%var as lua) + \(%val as lua)" +compile (%var -= %val) to code: "\(%var as lua) = \(%var as lua) - \(%val as lua)" +compile (%var *= %val) to code: "\(%var as lua) = \(%var as lua) * \(%val as lua)" +compile (%var /= %val) to code: "\(%var as lua) = \(%var as lua) / \(%val as lua)" +compile (%var ^= %val) to code: "\(%var as lua) = \(%var as lua) ^ \(%val as lua)" compile (%var and= %val) to code: "\(%var as lua) = \(%var as lua) and\(%val as lua)" compile (%var or= %val) to code: "\(%var as lua) = \(%var as lua) or \(%val as lua)" compile (%var join= %val) to code: "\(%var as lua) = \(%var as lua) .. \(%val as lua)" diff --git a/lib/permissions.nom b/lib/permissions.nom index 8d8b56d..a65fb67 100644 --- a/lib/permissions.nom +++ b/lib/permissions.nom @@ -4,17 +4,24 @@ require "lib/operators.nom" require "lib/collections.nom" # Permission functions +rule (standardize rules %rules) =: + if (lua expr "type(vars.rules) == 'string'"): %rules = [%rules] + (nomsu "get_stub" [%]) for all %rules rule (restrict %rules to within %elite-rules) =: + %rules =: standardize rules %rules + %elite-rules =: standardize rules %elite-rules say "Restricting \(%rules) to within \(%elite-rules)" for all (flatten [%elite-rules, %rules]): assert ((nomsu's "defs") has key %) "Undefined function: \(%)" - for all %rules: + for %rule in %rules: assert (nomsu "check_permission" [%]) ".." |You do not have permission to restrict permissions for function: \(%) - ((nomsu) ->* ["defs",%,"whiteset"]) =: - dict: [%, yes] for %it in %elite-rules + ((nomsu) ->* ["defs",%rule,"whiteset"]) =: + dict: [%, yes] for all %elite-rules rule (allow %elite-rules to use %rules) =: + %rules =: standardize rules %rules + %elite-rules =: standardize rules %elite-rules say "Allowing \(%elite-rules) to use \(%rules)" for all (flatten [%elite-rules, %rules]): assert ((nomsu's "defs") has key %) "Undefined function: \(%)" @@ -26,12 +33,14 @@ rule (allow %elite-rules to use %rules) =: for all %elite-rules: %whiteset -> % = (yes) rule (forbid %pleb-rules to use %rules) =: + %rules =: standardize rules %rules + %pleb-rules =: standardize rules %pleb-rules say "Forbidding \(%pleb-rules) to use \(%rules)" for all (flatten [%pleb-rules, %used]): assert ((nomsu's "defs") has key %) "Undefined function: \(%)" for all %rules: assert (nomsu "check_permission" [%]) ".." - |You do not have permission to grant permissions for function: \%it\ + |You do not have permission to grant permissions for function: \(%) %whiteset =: (nomsu) ->* ["defs",%,"whiteset"] assert %whiteset ".." |Cannot individually restrict permissions for \(%) because it is currently diff --git a/lib/plurals.nom b/lib/plurals.nom index 9df4060..d0cbcf0 100644 --- a/lib/plurals.nom +++ b/lib/plurals.nom @@ -18,18 +18,18 @@ with secrets: | return key |end}) - rule [the plural of %singular is %plural] =: + rule (the plural of %singular is %plural) =: (secret %plurals)->%singular =: %plural (secret %singulars)->%plural =: %singular (secret %canonicals)->%plural =: %singular - rule [singular %plural] =: + rule (singular %plural) =: %plural in (secret %singulars) - rule [plural %singular] =: + rule (plural %singular) =: %singular in (secret %plurals) - rule [canonicalize %item-name] =: + rule (canonicalize %item-name) =: %item-name in (secret %canonicals) - rule [rules that change plurals] =: ["the plural of % is %"] + rule (rules that change plurals) =: ["the plural of % is %"] diff --git a/lib/secrets.nom b/lib/secrets.nom index 756f988..d63ec8c 100644 --- a/lib/secrets.nom +++ b/lib/secrets.nom @@ -17,13 +17,4 @@ compile (secret %key = %new_value) to code: |Wrong type, expected Var, but got: \(%key's "type") "secrets[\(repr (%key's "value"))] = \(%new_value as lua)" -with secrets: - secret %foo = 5 - rule (plumb %) =: - secret %foo = % - rule (frop) =: - secret %foo - -say (frop) -plumb 99 -say (frop) +rule (rules about secrecy) =: ["with secrets %"] diff --git a/nomsu.lua b/nomsu.lua index 549e4f7..82a8b8f 100644 --- a/nomsu.lua +++ b/nomsu.lua @@ -95,7 +95,8 @@ local nomsu = [=[ file <- ({ {| shebang? word <- ({ !number {%wordchar (!"'" %wordchar)*} }) -> Word inline_string <- ({ '"' {| - ({~ (("\\" -> "\") / ('\"' -> '"') / (!string_interpolation [^%nl"]))+ ~} + ({~ (("\\" -> "\") / ('\"' -> '"') / ("\n" -> " +") / (!string_interpolation [^%nl"]))+ ~} / string_interpolation)* |} '"' }) -> String indented_string <- ({ '".."' indent {| indented_string_line (nodent {~ "" -> " diff --git a/nomsu.moon b/nomsu.moon index 217d576..80d000a 100755 --- a/nomsu.moon +++ b/nomsu.moon @@ -98,7 +98,8 @@ nomsu = [=[ word <- ({ !number {%wordchar (!"'" %wordchar)*} }) -> Word inline_string <- ({ '"' {| - ({~ (("\\" -> "\") / ('\"' -> '"') / (!string_interpolation [^%nl"]))+ ~} + ({~ (("\\" -> "\") / ('\"' -> '"') / ("\n" -> " +") / (!string_interpolation [^%nl"]))+ ~} / string_interpolation)* |} '"' }) -> String indented_string <- ({ '".."' indent {| indented_string_line (nodent {~ "" -> "