Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
palm86 committed May 6, 2021
1 parent ec03c92 commit 591716d
Show file tree
Hide file tree
Showing 7 changed files with 169 additions and 64 deletions.
21 changes: 16 additions & 5 deletions lib/joy/interpreter.ex
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,8 @@ defmodule Joy.Interpreter do
Prints a general or function-specific help message.
"""
def help(stack) do
{:docs_v1, _annotation, :elixir, _format, _module_doc, _metadata, docs} = Code.fetch_docs(__MODULE__)
{:docs_v1, _annotation, :elixir, _format, _module_doc, _metadata, docs} =
Code.fetch_docs(__MODULE__)

case stack do
[[name] | stack] ->
Expand All @@ -73,23 +74,33 @@ defmodule Joy.Interpreter do
unless String.starts_with?(to_string(name), "_") do
IO.puts(IO.ANSI.yellow() <> "\n" <> doc_content <> IO.ANSI.white() <> "\n")
end
_ -> :ok

_ ->
:ok
end)

stack

stack ->
IO.puts(IO.ANSI.yellow() <> "\nUsing backend #{inspect(__MODULE__)} which defines the following functions:\n")
IO.puts(
IO.ANSI.yellow() <>
"\nUsing backend #{inspect(__MODULE__)} which defines the following functions:\n"
)

docs
|> Enum.each(fn
{{:function, name, 1}, _, _, %{"en" => doc_content}, _metadata} ->
unless String.starts_with?(to_string(name), "_") do
IO.puts(" * " <> to_string(name))
end
_ -> :ok

_ ->
:ok
end)

IO.puts("\nUse `[name] help` to learn more about a specific function" <> IO.ANSI.yellow())
IO.puts(
"\nUse `[name] help` to learn more about a specific function" <> IO.ANSI.yellow()
)

stack
end
Expand Down
2 changes: 1 addition & 1 deletion lib/joy/interpreter/kerby.ex
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ defmodule Joy.Interpreter.Kerby do
See: http://tunes.org/~iepos/joy.html
"""
use Joy.Interpreter
require Logger
use Joy.Interpreter

@doc """
`[B] [A] swap == [A] [B]`
Expand Down
26 changes: 24 additions & 2 deletions lib/joy/parser.ex
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,34 @@ defmodule Joy.Parser do
{:error, "invalid token"}
end

{:error, _} ->
{:error, parser_error} ->
if bang do
raise "parser error"
else
{:error, "parser error"}
{:error, "parser error: #{inspect(parser_error)}"}
end
end
end

def tryme() do
# :joy_lexer.tokens()
:io.request(:stdout, {:get_until, :unicode, "prompt", :joy_lexer, :tokens, [0]})
end

def collect_action(chars, line, cont_0) do
case :joy_lexer.tokens(cont_0, chars, line) do
{:done, {:ok, tokens, _},_} -> {:ok, tokens, line};

{:done, {:eof, _},_} -> {:eof, line};

{:done, {:error, error, _},_} -> {:error, error,line};

{:more, cont_1} ->
collect_action(IO.gets("Miaau") |> to_charlist(), line + 1, cont_1)
end
end

def test() do
:joy_parser.parse_and_scan({__MODULE__, :tryme, []})
end
end
78 changes: 57 additions & 21 deletions lib/joy/repl.ex
Original file line number Diff line number Diff line change
Expand Up @@ -18,28 +18,64 @@ defmodule Joy.REPL do
end

defp loop(stack) do
# read
stack
|> read()
|> evaluate()
|> print()
|> loop()
end

# defp loop(stack) do
# # read
# input = IO.gets(IO.ANSI.magenta() <> "joy> " <> IO.ANSI.white())

# # evaluate
# stack =
# with {:ok, parsed_input} <- Joy.Parser.parse(input),
# {:ok, stack} <- Joy.Interpreter.interpret(parsed_input, stack) do
# # print
# stack
# |> Joy.Formatter.format(direction: :stack)
# |> IO.puts()

# stack
# else
# {:error, reason} ->
# # print
# IO.puts(IO.ANSI.red() <> "Error: #{inspect(reason)}" <> IO.ANSI.white())

# stack
# end

# # loop
# loop(stack)
# end

defp read(stack) do
input = IO.gets(IO.ANSI.magenta() <> "joy> " <> IO.ANSI.white())
{input, stack}
end

defp evaluate({input, stack}) do
with {:ok, parsed_input} <- Joy.Parser.parse(input),
{:ok, stack} <- Joy.Interpreter.interpret(parsed_input, stack) do
{:ok, stack}
else
{:error, reason} -> {:error, reason, stack}
end
end

defp print({:ok, stack}) do
stack
|> Joy.Formatter.format(direction: :stack)
|> IO.puts()

stack
end

defp print({:error, reason, stack}) do
IO.puts(IO.ANSI.red() <> "Error: #{inspect(reason)}" <> IO.ANSI.white())

# evaluate
stack =
with {:ok, parsed_input} <- Joy.Parser.parse(input),
{:ok, stack} <- Joy.Interpreter.interpret(parsed_input, stack) do
# print
stack
|> Joy.Formatter.format(direction: :stack)
|> IO.puts()

stack
else
{:error, reason} ->
# print
IO.puts(IO.ANSI.red() <> "Error: #{inspect(reason)}" <> IO.ANSI.white())

stack
end

# loop
loop(stack)
stack
end
end
81 changes: 48 additions & 33 deletions src/joy_lexer.erl
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
-export([format_error/1]).

%% User code. This is placed here to allow extra attributes.
-file("src/joy_lexer.xrl", 15).
-file("src/joy_lexer.xrl", 17).

to_atom(Chars) ->
list_to_atom(Chars).
Expand Down Expand Up @@ -309,8 +309,10 @@ adjust_line(T, A, [_|Cs], L) ->
%% input.

-file("src/joy_lexer.erl", 310).
yystate() -> 3.
yystate() -> 2.

yystate(5, Ics, Line, Tlen, _, _) ->
{1,Tlen,Ics,Line};
yystate(4, [32|Ics], Line, Tlen, _, _) ->
yystate(4, Ics, Line, Tlen+1, 3, Tlen);
yystate(4, [13|Ics], Line, Tlen, _, _) ->
Expand All @@ -321,42 +323,48 @@ yystate(4, [10|Ics], Line, Tlen, _, _) ->
yystate(4, Ics, Line+1, Tlen+1, 3, Tlen);
yystate(4, Ics, Line, Tlen, _, _) ->
{3,Tlen,Ics,Line,4};
yystate(3, [95|Ics], Line, Tlen, Action, Alen) ->
yystate(2, Ics, Line, Tlen+1, Action, Alen);
yystate(3, [93|Ics], Line, Tlen, Action, Alen) ->
yystate(3, [95|Ics], Line, Tlen, _, _) ->
yystate(3, Ics, Line, Tlen+1, 0, Tlen);
yystate(3, [45|Ics], Line, Tlen, _, _) ->
yystate(3, Ics, Line, Tlen+1, 0, Tlen);
yystate(3, [C|Ics], Line, Tlen, _, _) when C >= 48, C =< 57 ->
yystate(3, Ics, Line, Tlen+1, 0, Tlen);
yystate(3, [C|Ics], Line, Tlen, _, _) when C >= 97, C =< 122 ->
yystate(3, Ics, Line, Tlen+1, 0, Tlen);
yystate(3, Ics, Line, Tlen, _, _) ->
{0,Tlen,Ics,Line,3};
yystate(2, [95|Ics], Line, Tlen, Action, Alen) ->
yystate(3, Ics, Line, Tlen+1, Action, Alen);
yystate(2, [93|Ics], Line, Tlen, Action, Alen) ->
yystate(1, Ics, Line, Tlen+1, Action, Alen);
yystate(3, [91|Ics], Line, Tlen, Action, Alen) ->
yystate(2, [91|Ics], Line, Tlen, Action, Alen) ->
yystate(5, Ics, Line, Tlen+1, Action, Alen);
yystate(2, [45|Ics], Line, Tlen, Action, Alen) ->
yystate(3, Ics, Line, Tlen+1, Action, Alen);
yystate(2, [35|Ics], Line, Tlen, Action, Alen) ->
yystate(0, Ics, Line, Tlen+1, Action, Alen);
yystate(3, [45|Ics], Line, Tlen, Action, Alen) ->
yystate(2, Ics, Line, Tlen+1, Action, Alen);
yystate(3, [32|Ics], Line, Tlen, Action, Alen) ->
yystate(2, [32|Ics], Line, Tlen, Action, Alen) ->
yystate(4, Ics, Line, Tlen+1, Action, Alen);
yystate(3, [13|Ics], Line, Tlen, Action, Alen) ->
yystate(2, [13|Ics], Line, Tlen, Action, Alen) ->
yystate(4, Ics, Line, Tlen+1, Action, Alen);
yystate(3, [9|Ics], Line, Tlen, Action, Alen) ->
yystate(2, [9|Ics], Line, Tlen, Action, Alen) ->
yystate(4, Ics, Line, Tlen+1, Action, Alen);
yystate(3, [10|Ics], Line, Tlen, Action, Alen) ->
yystate(2, [10|Ics], Line, Tlen, Action, Alen) ->
yystate(4, Ics, Line+1, Tlen+1, Action, Alen);
yystate(3, [C|Ics], Line, Tlen, Action, Alen) when C >= 48, C =< 57 ->
yystate(2, Ics, Line, Tlen+1, Action, Alen);
yystate(3, [C|Ics], Line, Tlen, Action, Alen) when C >= 97, C =< 122 ->
yystate(2, Ics, Line, Tlen+1, Action, Alen);
yystate(3, Ics, Line, Tlen, Action, Alen) ->
{Action,Alen,Tlen,Ics,Line,3};
yystate(2, [95|Ics], Line, Tlen, _, _) ->
yystate(2, Ics, Line, Tlen+1, 0, Tlen);
yystate(2, [45|Ics], Line, Tlen, _, _) ->
yystate(2, Ics, Line, Tlen+1, 0, Tlen);
yystate(2, [C|Ics], Line, Tlen, _, _) when C >= 48, C =< 57 ->
yystate(2, Ics, Line, Tlen+1, 0, Tlen);
yystate(2, [C|Ics], Line, Tlen, _, _) when C >= 97, C =< 122 ->
yystate(2, Ics, Line, Tlen+1, 0, Tlen);
yystate(2, Ics, Line, Tlen, _, _) ->
{0,Tlen,Ics,Line,2};
yystate(2, [C|Ics], Line, Tlen, Action, Alen) when C >= 48, C =< 57 ->
yystate(3, Ics, Line, Tlen+1, Action, Alen);
yystate(2, [C|Ics], Line, Tlen, Action, Alen) when C >= 97, C =< 122 ->
yystate(3, Ics, Line, Tlen+1, Action, Alen);
yystate(2, Ics, Line, Tlen, Action, Alen) ->
{Action,Alen,Tlen,Ics,Line,2};
yystate(1, Ics, Line, Tlen, _, _) ->
{2,Tlen,Ics,Line};
yystate(0, [C|Ics], Line, Tlen, _, _) when C >= 0, C =< 9 ->
yystate(0, Ics, Line, Tlen+1, 4, Tlen);
yystate(0, [C|Ics], Line, Tlen, _, _) when C >= 11 ->
yystate(0, Ics, Line, Tlen+1, 4, Tlen);
yystate(0, Ics, Line, Tlen, _, _) ->
{1,Tlen,Ics,Line};
{4,Tlen,Ics,Line,0};
yystate(S, Ics, Line, Tlen, Action, Alen) ->
{Action,Alen,Tlen,Ics,Line,S}.

Expand All @@ -373,26 +381,33 @@ yyaction(2, _, _, TokenLine) ->
yyaction_2(TokenLine);
yyaction(3, _, _, _) ->
yyaction_3();
yyaction(4, _, _, _) ->
yyaction_4();
yyaction(_, _, _, _) -> error.

-compile({inline,yyaction_0/2}).
-file("src/joy_lexer.xrl", 8).
-file("src/joy_lexer.xrl", 9).
yyaction_0(TokenChars, TokenLine) ->
{ token, { function, TokenLine, to_atom (TokenChars) } } .

-compile({inline,yyaction_1/1}).
-file("src/joy_lexer.xrl", 9).
-file("src/joy_lexer.xrl", 10).
yyaction_1(TokenLine) ->
{ token, { '[', TokenLine } } .

-compile({inline,yyaction_2/1}).
-file("src/joy_lexer.xrl", 10).
-file("src/joy_lexer.xrl", 11).
yyaction_2(TokenLine) ->
{ token, { ']', TokenLine } } .

-compile({inline,yyaction_3/0}).
-file("src/joy_lexer.xrl", 11).
-file("src/joy_lexer.xrl", 12).
yyaction_3() ->
skip_token .

-compile({inline,yyaction_4/0}).
-file("src/joy_lexer.xrl", 13).
yyaction_4() ->
skip_token .

-file("/usr/local/Cellar/erlang/22.3.4/lib/erlang/lib/parsetools-2.1.8/include/leexinc.hrl", 313).
2 changes: 2 additions & 0 deletions src/joy_lexer.xrl
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,15 @@ Definitions.

FUNCTION = [a-z_0-9\-]+
WHITESPACE = [\s\t\n\r]+
COMMENT = #.*

Rules.

{FUNCTION} : {token, {function, TokenLine, to_atom(TokenChars)}}.
\[ : {token, {'[', TokenLine}}.
\] : {token, {']', TokenLine}}.
{WHITESPACE} : skip_token.
{COMMENT} : skip_token.

Erlang code.

Expand Down
23 changes: 21 additions & 2 deletions test/joy_lexer_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,27 @@ defmodule JoyLexerTest do
test "newlines" do
str = """
[
a
[]
a
[]
]
"""

assert {:ok, tokens, _} = str |> to_charlist() |> :joy_lexer.string()

assert tokens == [
{:"[", 1},
{:function, 2, :a},
{:"[", 3},
{:"]", 3},
{:"]", 4},
]
end

test "comments" do
str = """
[
a # just a comment
[]
]
"""

Expand Down

0 comments on commit 591716d

Please sign in to comment.