Skip to content
Browse files

Initial support for dispatching class method calls

  • Loading branch information...
1 parent 08f87dc commit ce67bb254946aedf8ce6511cce9f60474d2e3b75 Tony Arcieri committed
Showing with 62 additions and 34 deletions.
  1. +36 −26 src/core/reia.erl
  2. +26 −8 src/core/reia_dispatch.erl
View
62 src/core/reia.erl
@@ -7,13 +7,15 @@
-module(reia).
-export([
- init/0,
- load/1,
- parse/1,
- eval/2,
- inst/2, inst/3,
- invoke/3, invoke/4,
- throw/2, throw/3
+ init/0,
+ load/1,
+ parse/1,
+ eval/2,
+ inst/2, inst/3,
+ invoke/3, invoke/4,
+ throw/2, throw/3,
+ list_to_string/1,
+ binary_to_string/1
]).
-include("reia_types.hrl").
@@ -36,34 +38,42 @@ load(Filename) ->
% Parse the given string of Reia source code
parse(String) ->
- reia_compiler:parse(String).
+ reia_compiler:parse(String).
% Evaluate the given string of Reia source code
eval(String, Binding) ->
- reia_eval:exprs(parse(String), Binding).
-
+ reia_eval:exprs(parse(String), Binding).
+
% Create a new instance of the given class
inst(Class, Arguments) -> inst(Class, Arguments, nil).
inst(Class, Arguments, Block) ->
- % FIXME: initial object construction should thunk to the metaclass, not be
- % spelled out explicitly here.
- Object = #reia_object{class=Class, ivars=dict:new()},
- Class:call({Object, initialize, Arguments}, Block).
-
+ % FIXME: initial object construction should thunk to the metaclass, not be
+ % spelled out explicitly here.
+ Object = #reia_object{class=Class, ivars=dict:new()},
+ Class:call({Object, initialize, Arguments}, Block).
+
% Invoke the given method on the given object
invoke(Receiver, Method, Arguments) -> invoke(Receiver, Method, Arguments, nil).
invoke(Receiver, Method, Arguments, Block) ->
- Arguments2 = if
- is_tuple(Arguments) -> Arguments;
- is_list(Arguments) -> list_to_tuple(Arguments);
- true -> throw({error, "invalid type for arguments"})
- end,
-
- Class = Receiver#reia_object.class,
- Class:call({Receiver, Method, Arguments2}, Block).
-
+ Arguments2 = if
+ is_tuple(Arguments) -> Arguments;
+ is_list(Arguments) -> list_to_tuple(Arguments);
+ true -> throw({error, "invalid type for arguments"})
+ end,
+
+ Class = Receiver#reia_object.class,
+ Class:call({Receiver, Method, Arguments2}, Block).
+
% Throw a Reia exception
throw(Class, Message) ->
- throw(Class, nil, Message).
+ throw(Class, nil, Message).
throw(Class, Line, Message) ->
- erlang:throw(inst(Class, {Line, Message})).
+ erlang:throw(inst(Class, {Line, Message})).
+
+% Convert an Erlang list to a Reia string
+list_to_string(List) ->
+ #reia_string{elements=List}.
+
+% Convert an Erlang binary to a Reia string
+binary_to_string(Bin) ->
+ #reia_string{elements=Bin}.
View
34 src/core/reia_dispatch.erl
@@ -26,14 +26,8 @@ call(#reia_regexp{} = Receiver, Method, Arguments, Block) ->
'Regexp':call({Receiver, Method, Arguments}, Block);
call(#reia_range{} = Receiver, Method, Arguments, Block) ->
'Range':call({Receiver, Method, Arguments}, Block);
-call(#reia_module{name=Name} = Receiver, Method, Arguments, Block) ->
- case code:ensure_loaded(Name) of
- {module, Name} ->
- 'Module':call({Receiver, Method, Arguments, Block}, nil);
- _ ->
- Message = lists:flatten(io_lib:format("undefined module ~s", [Name])),
- reia:throw('NameError', Message)
- end;
+call(#reia_module{} = Receiver, Method, Arguments, Block) ->
+ dispatch_module_call(Receiver, Method, Arguments, Block);
call(#reia_funref{} = Receiver, Method, Arguments, Block) ->
'Funref':call({Receiver, Method, Arguments}, Block);
call(Receiver, Method, Arguments, Block) when is_tuple(Receiver) ->
@@ -56,3 +50,27 @@ call(Receiver, Method, Arguments, Block) when is_port(Receiver) ->
'Channel':call({Receiver, Method, Arguments}, Block);
call(Receiver, _, _, _) ->
throw({error, unknown_receiver, Receiver}).
+
+dispatch_module_call(#reia_module{name=Name} = Receiver, Method, Arguments, Block) ->
+ case code:ensure_loaded(Name) of
+ {module, Name} ->
+ Attributes = Name:module_info(attributes),
+ case proplists:get_value(module_type, Attributes) of
+ [module] ->
+ 'Module':call({Receiver, Method, Arguments, Block}, nil);
+ [class] ->
+ % FIXME: to_s and inspect shouldn't be implemented here!
+ case Method of
+ to_s -> reia:list_to_string(atom_to_list(Name));
+ inspect -> reia:list_to_string(atom_to_list(Name));
+ _ ->
+ reia:throw('RuntimeError', "class methods not implemented yet, sorry!")
+ end;
+ undefined ->
+ Message = lists:flatten(io_lib:format("missing module_type attribute in ~s", [Name])),
+ reia:throw('RuntimeError', Message)
+ end;
+ _ ->
+ Message = lists:flatten(io_lib:format("undefined module ~s", [Name])),
+ reia:throw('NameError', Message)
+ end.

0 comments on commit ce67bb2

Please sign in to comment.
Something went wrong with that request. Please try again.