Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Updating #3

Open
SquidDev opened this issue Jul 21, 2015 · 8 comments
Open

Updating #3

SquidDev opened this issue Jul 21, 2015 · 8 comments

Comments

@SquidDev
Copy link
Collaborator

I don't think it is implemented - updating would be really nice. Something like grin-get update [package name...]. Leaving it blank would update everything, specifying packages would attempt to update them.

I'm happy to put together a PR, just thought I would ask you first.

@ElvishJerricco
Copy link
Member

Yea this is rather important. Grin-Get has a whole bunch of things that ought to be implemented. If I weren't so busy as well as focused on other projects, there's a lot I would do with it.

@SquidDev
Copy link
Collaborator Author

I'm just seeing a bit more interest in ClamShell and think it would be nice if Grin-Get were a bit more fully-featured. I'll put something together in the next week or so.

@ElvishJerricco
Copy link
Member

True. I need to start looking at expanding the Bish language for ClamShell. I read up on monadic parsing in haskell (which is fascinating). I'd like to redesign the parser to be as monadic as Lua can concisely be, and I'd like to use the improved parser to implement some desirable language features.

@SquidDev
Copy link
Collaborator Author

Looks pretty cool! The composition element reminds me of Sprache and LPeg. I think Moonscript's parser is powered by LPeg, and I have considered using it for ClamShell, though monadic parsing would be more powerful.

My one worry is error messages - neither Sprache or Moonscript produce the most accurate error messages and locations are not always as where they should be.

@ElvishJerricco
Copy link
Member

I actually went ahead and got started on a library last night =P

parsel.symbol"local":bind(function(a) -- a is the string "local"
    -- Haven't made a simple "identifier" parser yet...
    return parsel.satisfy(function(c) return c:find("%a") ~= nil end)
    :many1() -- at least one
    :token() -- make it consume trailing whitespace
    :sepBy1(parsel.symbol",") -- parse multiple (at least one) instance, separated by comma
    :bind(function(names)
        -- names is the array of parsed names
        return parsel.symbol("="):bind(function(equals)
            return someExpressionParser()
        end)
    end)
end)

That will parse Lua's local declarations (excluding the expression parser). It's a bit cumbersome to use the bind operator without Haskell's do notation, but I'm looking into workarounds. For example, something like this might make it easier.

bindMany(startingMonad,
function(startsReturn) return getter end,
function(thatsReturn) return otherGetter end,
function(all, three, returns)
    -- perform computation on all three gotten values
    return computation
end)

-- Also the >> operator in haskell
someParser:sequence(otherParser)
-- equivalent to
someParser:bind(function(a) return otherParser end)

@SquidDev
Copy link
Collaborator Author

One thing you could do would be two wrap the functions with metatables to add custom operators. So for instance a .. b could be parse a then b (a sequence, from what I can tell the >>= operator) and then a + b would be the same but without preserving the value of a?

I'm probably just missing the point of moands here. My knowledge of functional programming starts and stops with lambdas. It does look really cool though!

@ElvishJerricco
Copy link
Member

Haha yea you're missing the purpose of bind (>>=) but you've got the other bind operator (>>) correct.

a >>= \x -> return (someOp x)

Note that return is a function, not a language keyword. It takes a value and wraps it in the contextual monad. The parsel equivalent is from, since I can't use the return keyword. Bind unwraps the value in a and calls the function with that as the parameter. Then bind returns something based on the return of that function (often just whatever that function returned exactly).

So it's not a .. b, it's a .. function(a) return from(someOp(a)) end The >> operator can be done that way though, since it basically means this

a >> b = a >>= \x -> b

meaning that it's just returning b without any regard for x.

@SquidDev
Copy link
Collaborator Author

Having read some article I think I understand. It is confusing the two bind operators taking two different values (in one, a parser, the other a function that returns a parser).

In other news: I added something to your code.

local a = parsel.symbol "a"
local abtest = (a/"b"/"test"):many() -- Functions are converted to parsers, strings to symbols.

-- abtest:between("{", "}") also works. Less fun though - but much more useful.
local braces = ("{" .. abtest .. "}") % function(obj) return obj[2][1] end
local p = (abtest .. braces) % function(res) return { outer = res[1], inner = res[2]} end

local success, result, remaining = p(...)

The / symbol is aliased to :otherwise, + to :bind, % to :fmap.

- is also aliased to :discardBind, though that I'm less sure about. As you can see the .. operator isn't great:

"{" .. func .. "}"
-- Results in
{ "{", { result, "}" } }

Each operator wraps the previous two, which isn't great so you have to manually the required variable. You can simplify with:

("{" - abtest .. "}") % function(obj) return obj[1] end

I'm not suggesting you use it - though I do like the / and % features.

Other features I think would be cool would be a * 2 repeats exactly two times. Also a bounds feature: a ^ {2, 3} 2 or 3 times. You could also write a ^ {0, 2} and a ^ {2,}/a ^ 2 to have repeat at most twice and twice or more.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants