Projects
openEuler:Mainline
erlang-lfe
Sign Up
Log In
Username
Password
We truncated the diff of some files because they were too big. If you want to see the full diff for every file,
click here
.
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
Expand all
Collapse all
Changes of Revision 2
View file
_service:tar_scm:erlang-lfe.spec
Changed
@@ -6,15 +6,14 @@ %global debug_package %{nil} %endif Name: erlang-%{realname} -Version: 1.3 +Version: 2.1.1 Release: 1 Summary: Lisp Flavoured Erlang License: BSD URL: https://github.com/%{upstream}/%{realname} VCS: scm:git:https://github.com/%{upstream}/%{realname}.git Source0: https://github.com/%{upstream}/%{realname}/archive/%{version}/%{realname}-%{version}.tar.gz -Patch1: erlang-lfe-0001-Remove-support-for-erlang-packages.patch -Patch2: erlang-lfe-0002-Convert-to-proper-UTF-8.patch + %if 0%{?need_bootstrap} BuildRequires: erlang-erts erlang-rpm-macros %else @@ -32,8 +31,6 @@ %prep %setup -q -n %{realname}-%{version} -%patch1 -p1 -b .no_erl_packages -%patch2 -p1 -b .proper_utf8 %build %if 0%{?need_bootstrap} @@ -88,5 +85,8 @@ %{_emacs_sitestartdir}/lfe-start.el %changelog +* Tue Feb 28 2023 lilong <lilong@kylinos.cn> - 2.1.1-1 +- Upgrade to 2.1.1 + * Sat Aug 29 2020 wangyue <wangyue92@huawei.com> - 1.3-1 - package init
View file
_service:tar_scm:erlang-lfe-0001-Remove-support-for-erlang-packages.patch
Deleted
@@ -1,39 +0,0 @@ -From: Peter Lemenkov <lemenkov@gmail.com> -Date: Thu, 31 Mar 2016 08:49:49 +0300 -Subject: PATCH Remove support for erlang packages. - -Erlang "packages" were abandoned long time ago. Remaining support was -dropped in erlang/otp@8e32c07940d9cd1c325d052bded3729333920f81. - -Signed-off-by: Peter Lemenkov <lemenkov@gmail.com> - -diff --git a/src/lfe_trans.erl b/src/lfe_trans.erl -index d2d21b2..628e4eb 100644 ---- a/src/lfe_trans.erl -+++ b/src/lfe_trans.erl -@@ -139,8 +139,6 @@ from_expr({record_field,_,E,R,{atom,_,F}}, Vt0, St0) -> %We KNOW! - RF = list_to_atom(atom_to_list(R) ++ "-" ++ atom_to_list(F)), - {Le,Vt1,St1} = from_expr(E, Vt0, St0), - {RF,Le,Vt1,St1}; --from_expr({record_field,_,_,_}=M, Vt, St) -> %Pre R16 packages -- from_package_module(M, Vt, St); - %% Function calls. - from_expr({call,_,{remote,_,M,F},As}, Vt0, St0) -> %Remote function call - {Lm,Vt1,St1} = from_expr(M, Vt0, St0), -@@ -367,16 +365,6 @@ from_rec_fields({record_field,_,{var,_,F},E}|Fs, Vt0, St0) -> %special case!! - {F,Le|Lfs,Vt2,St2}; - from_rec_fields(, Vt, St) -> {,Vt,St}. - --%% from_package_module(Module, VarTable, State) -> {Module,VarTable,State}. --%% We must handle the special case where in pre-R16 you could have --%% packages with a dotted module path. It used a special record_field --%% tuple. This does not work in R16 and later! -- --from_package_module({record_field,_,_,_}=M, Vt, St) -> -- Segs = erl_parse:package_segments(M), -- A = list_to_atom(packages:concat(Segs)), -- {?Q(A),Vt,St}. -- - from_maybe(_, ) -> ; - from_maybe(Tag, Es) -> Tag|Es. -
View file
_service:tar_scm:erlang-lfe-0002-Convert-to-proper-UTF-8.patch
Deleted
@@ -1,19 +0,0 @@ -From: Peter Lemenkov <lemenkov@gmail.com> -Date: Tue, 20 Jun 2017 18:24:11 +0300 -Subject: PATCH Convert to proper UTF-8 - -Signed-off-by: Peter Lemenkov <lemenkov@gmail.com> - -diff --git a/examples/core-macros.lfe b/examples/core-macros.lfe -index e76148a..3cac342 100644 ---- a/examples/core-macros.lfe -+++ b/examples/core-macros.lfe -@@ -96,7 +96,7 @@ - (() `'false))) - - ;; This version of backquote is almost an exact copy of a quasiquote --;; expander for Scheme by André van Tonder. It is very compact and -+;; expander for Scheme by André van Tonder. It is very compact and - ;; with some cons/append optimisations we have added produces quite - ;; reasonable code. -
View file
_service
Changed
@@ -2,7 +2,7 @@ <service name="tar_scm"> <param name="scm">git</param> <param name="url">git@gitee.com:src-openeuler/erlang-lfe.git</param> - <param name="revision">284127a8d941f2673173d41ac8f3ecb4d4b17eca</param> + <param name="revision">master</param> <param name="exclude">*</param> <param name="extract">*</param> </service>
View file
_service:tar_scm:lfe-1.3.tar.gz/.travis.yml
Deleted
@@ -1,18 +0,0 @@ -language: erlang -install: true -before_script: - - wget https://s3.amazonaws.com/rebar3/rebar3 - - chmod +x rebar3 -env: PATH=$PATH:. -script: make travis -notifications: - disabled: true -otp_release: - - 19.0 - - 18.2 - - 18.0 - - 17.5 - - 17.1 - - R16B03-1 - # - R15B03 - # - R14B04
View file
_service:tar_scm:lfe-1.3.tar.gz/dev/record-defs.lfe
Deleted
@@ -1,3 +0,0 @@ -(defrecord point x y) - -(defrecord circle center radius)
View file
_service:tar_scm:lfe-1.3.tar.gz/dev/test_pmod_base.lfe
Deleted
@@ -1,22 +0,0 @@ -(defmodule (test_pmod_base x y) - (export (m1 2) (m2 1) (m3 1) (m4 1)) - (export all) - (import (from lists (reverse 1)))) - -(defun m1 - (('a a) (xxx 1 x)) - (('b a) (xxx 2 x))) - -(defun m2 (z) - (flet ((xxx (z) (tuple x y z))) - (xxx z))) - -(defun m3 (z) (tuple (b1 z) (reverse z) this)) - -(defun m4 (z) (: para_2 a1 z)) - -(defun b1 (z) (length z)) - -(defun b2 (z) (tuple x y (length z))) - -(defun xxx (a b) (cons a b))
View file
_service:tar_scm:lfe-1.3.tar.gz/dev/test_pmod_ext.lfe
Deleted
@@ -1,22 +0,0 @@ -(defmodule (test_pmod_ext x y) - (extends test_pmod_base) - (export (a1 2) (a2 1) (a3 1) (a4 1)) - (import (from lists (reverse 1)))) - -(defun a1 - (('a a) (xxx 1 x)) - (('b a) (xxx 2 x))) - -(defun a2 (z) - (flet ((xxx (z) (tuple x y z))) - (xxx z))) - -(defun a3 (z) (tuple (b1 z) (reverse z) this base)) - -(defun a4 (z) (: para_2 a1 z)) - -(defun b1 (z) (length z)) - -(defun b2 (z) (tuple x y (length z))) - -(defun xxx (a b) (cons a b))
View file
_service:tar_scm:lfe-1.3.tar.gz/doc/lfe_doc.txt
Deleted
@@ -1,88 +0,0 @@ -lfe_doc(3) lfe_doc(3) - - - -NAME - lfe_doc - Lisp Flavoured Erlang (LFE) documentation parser. - -SYNOPSIS - This module provides functions to parse docstrings in LFE module - sources. - - There is no guarantee the internal formats will not change but the in‐ - terface functions should stay the same. - -EXPORTS - extract_module_docs(Mod, CompilerInfo) -> {ok,ModDocs} | {error,Er‐ - rors,} - - Parse a module's docstrings and return module documentation structure. - - save_module_docs(Beam, ModDocs, CompilerInfo) -> Beam - - Add the "LDoc" chunk containing ModDocs to a module's .beam binary. - - get_module_docs(Module | Binary) -> {ok,DocChunk} | {error,Error} - - Extract the documentation chunk from a module. The chunk will be con‐ - verted to an internal format. - - format_docs/1 - - Take a list of doc strings and generate a list of indented doc lines. - Each doc string is indented separately. - - format_error(ErrorDecriptor) -> Chars - - Given an ErrorDescriptor, return a deep list of characters which de‐ - scribe the error. This function is usually called implicitly when an - ErrorInfo structure is processed. See lfe_comp(3). - - N.B. Currently, format_error/1 always returns "doc error". - - MODULE DOC ACCESSORS - module_doc(DocChunk) -> DocString - - mf_docs(DocChunk) -> MacFuncDoc - - mf_doc_type(MacFuncDoc) -> function | macro - - function_docs(DocChunk) -> FuncDoc - - macro_docs(DocChunk) -> MacDoc - - Extract fields from the module documentation chunk. - - FUNCTION DOC ACCESSORS - function_name(FuncDoc) -> Name - - function_arity(FuncDoc) -> Arity - - function_line(FuncDoc) -> Line - - function_patterns(FuncDoc) -> Pattern - - function_doc(FuncDoc) -> DocString - - Extract fields from a function documentation structure. - - MACRO DOC ACCESSORS - macro_name(MacDoc) -> Name - - macro_line(MacDoc) -> Line - - macro_patterns(MacDoc) -> Pattern - - macro_doc(MacDoc) -> DocString - - Extract fields from a macro documentation structure. - -SEE ALSO - lfe_comp(3), lfe_macro(3) - -AUTHORS - Eric Bailey. - - - - 2016 lfe_doc(3)
View file
_service:tar_scm:lfe-1.3.tar.gz/doc/man/lfe_doc.3
Deleted
@@ -1,90 +0,0 @@ -.\" Automatically generated by Pandoc 1.19.2.1 -.\" -.TH "lfe_doc" "3" "2016" "" "" -.hy -.SH NAME -.PP -lfe_doc \- Lisp Flavoured Erlang (LFE) documentation parser. -.SH SYNOPSIS -.PP -This module provides functions to parse docstrings in LFE module -sources. -.PP -There is no guarantee the internal formats will not change but the -interface functions should stay the same. -.SH EXPORTS -.PP -\fBextract_module_docs(Mod, CompilerInfo) \-> {ok,ModDocs} | -{error,Errors,}\f -.PP -Parse a module\aqs docstrings and return module documentation -structure. -.PP -\fBsave_module_docs(Beam, ModDocs, CompilerInfo) \-> Beam\f -.PP -Add the \fC"LDoc"\f chunk containing \fCModDocs\f to a -module\aqs .beam binary. -.PP -\fBget_module_docs(Module | Binary) \-> {ok,DocChunk} | -{error,Error}\f -.PP -Extract the documentation chunk from a module. -The chunk will be converted to an internal format. -.PP -\fBformat_docs/1\f -.PP -Take a list of doc strings and generate a list of indented doc lines. -Each doc string is indented separately. -.PP -\fBformat_error(ErrorDecriptor) \-> Chars\f -.PP -Given an \fCErrorDescriptor\f, return a deep list of characters -which describe the error. -This function is usually called implicitly when an \fCErrorInfo\f -structure is processed. -See \fBlfe_comp(3)\f. -.PP -N.B. -Currently, \fCformat_error/1\f always returns \fC"doc\ error"\f. -.SS MODULE DOC ACCESSORS -.PP -\fBmodule_doc(DocChunk) \-> DocString\f -.PP -\fBmf_docs(DocChunk) \-> MacFuncDoc\f -.PP -\fBmf_doc_type(MacFuncDoc) \-> function | macro\f -.PP -\fBfunction_docs(DocChunk) \-> FuncDoc\f -.PP -\fBmacro_docs(DocChunk) \-> MacDoc\f -.PP -Extract fields from the module documentation chunk. -.SS FUNCTION DOC ACCESSORS -.PP -\fBfunction_name(FuncDoc) \-> Name\f -.PP -\fBfunction_arity(FuncDoc) \-> Arity\f -.PP -\fBfunction_line(FuncDoc) \-> Line\f -.PP -\fBfunction_patterns(FuncDoc) \-> Pattern\f -.PP -\fBfunction_doc(FuncDoc) \-> DocString\f -.PP -Extract fields from a function documentation structure. -.SS MACRO DOC ACCESSORS -.PP -\fBmacro_name(MacDoc) \-> Name\f -.PP -\fBmacro_line(MacDoc) \-> Line\f -.PP -\fBmacro_patterns(MacDoc) \-> Pattern\f -.PP -\fBmacro_doc(MacDoc) \-> DocString\f -.PP -Extract fields from a macro documentation structure. -.SH SEE ALSO -.PP -\fBlfe_comp(3)\f, \fBlfe_macro(3)\f -.SH AUTHORS -Eric Bailey.
View file
_service:tar_scm:lfe-1.3.tar.gz/doc/src/lfe_doc.3.md
Deleted
@@ -1,92 +0,0 @@ -% lfe_doc(3) -% Eric Bailey -% 2016 - - -# NAME - -lfe_doc - Lisp Flavoured Erlang (LFE) documentation parser. - - -# SYNOPSIS - -This module provides functions to parse docstrings in LFE module sources. - -There is no guarantee the internal formats will not change -but the interface functions should stay the same. - - -# EXPORTS - -**extract_module_docs(Mod, CompilerInfo) -> {ok,ModDocs} | {error,Errors,}** - -Parse a module's docstrings and return module documentation structure. - -**save_module_docs(Beam, ModDocs, CompilerInfo) -> Beam** - -Add the ``"LDoc"`` chunk containing ``ModDocs`` to a module's .beam binary. - -**get_module_docs(Module | Binary) -> {ok,DocChunk} | {error,Error}** - -Extract the documentation chunk from a module. The chunk will be -converted to an internal format. - -**format_docs/1** - -Take a list of doc strings and generate a list of indented doc -lines. Each doc string is indented separately. - -**format_error(ErrorDecriptor) -> Chars** - -Given an ``ErrorDescriptor``, return a deep list of characters which describe -the error. This function is usually called implicitly when an ``ErrorInfo`` -structure is processed. See **lfe_comp(3)**. - -N.B. Currently, ``format_error/1`` always returns ``"doc error"``. - - -### MODULE DOC ACCESSORS - -**module_doc(DocChunk) -> DocString** - -**mf_docs(DocChunk) -> MacFuncDoc** - -**mf_doc_type(MacFuncDoc) -> function | macro** - -**function_docs(DocChunk) -> FuncDoc** - -**macro_docs(DocChunk) -> MacDoc** - -Extract fields from the module documentation chunk. - -### FUNCTION DOC ACCESSORS - -**function_name(FuncDoc) -> Name** - -**function_arity(FuncDoc) -> Arity** - -**function_line(FuncDoc) -> Line** - -**function_patterns(FuncDoc) -> Pattern** - -**function_doc(FuncDoc) -> DocString** - -Extract fields from a function documentation structure. - - -### MACRO DOC ACCESSORS - -**macro_name(MacDoc) -> Name** - -**macro_line(MacDoc) -> Line** - -**macro_patterns(MacDoc) -> Pattern** - -**macro_doc(MacDoc) -> DocString** - -Extract fields from a macro documentation structure. - - -# SEE ALSO - -**lfe_comp(3)**, **lfe_macro(3)**
View file
_service:tar_scm:lfe-1.3.tar.gz/rebar.lock
Deleted
@@ -1,1 +0,0 @@ -.
View file
_service:tar_scm:lfe-1.3.tar.gz/src/lfe_doc.erl
Deleted
@@ -1,387 +0,0 @@ -%% Copyright (c) 2016 Eric Bailey -%% -%% Licensed under the Apache License, Version 2.0 (the "License"); -%% you may not use this file except in compliance with the License. -%% You may obtain a copy of the License at -%% -%% http://www.apache.org/licenses/LICENSE-2.0 -%% -%% Unless required by applicable law or agreed to in writing, software -%% distributed under the License is distributed on an "AS IS" BASIS, -%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%% See the License for the specific language governing permissions and -%% limitations under the License. - -%% File : lfe_doc.erl -%% Author : Eric Bailey -%% Purpose : Lisp Flavoured Erlang (LFE) documentation parser. - -%% There is no guarantee the internal formats will not change -%% but the interface functions should stay the same. - --module(lfe_doc). - --export(format_error/1). - --export(extract_module_docs/1,extract_module_docs/2,save_module_docs/3). - -%% Access functions for documentation in modules. --export(get_module_docs/1,module_doc/1,mf_docs/1,mf_doc_type/1, - function_docs/3,macro_docs/2, - function_name/1,function_arity/1,function_line/1, - function_patterns/1, function_doc/1, - macro_name/1,macro_line/1,macro_patterns/1,macro_doc/1). - --export(format_docs/1). - --import(lists, member/2,filter/2,foldl/3,foldr/3,reverse/1). - --include("lfe_comp.hrl"). --include("lfe_doc.hrl"). - --ifdef(EUNIT). --export(collect_docs/2,pprint/2). %Used by prop_lfe_doc - --include_lib("eunit/include/eunit.hrl"). - --define(QC_OPTS, {on_output,fun pprint/2},{numtests,1000},{max_size,10}). --define(QC(T,P), {timeout,30,{T,?_assert(proper:quickcheck(P, ?QC_OPTS))}}). --endif. - -%% Errors -format_error(_) -> "doc error". - -%% extract_module_docs(Defs, CompInfo) -> {ok,Docs} | {error,Errors,}. -%% Parse a module's docstrings and return the docs. - --spec extract_module_docs(Defs, Cinfo) -> {ok,Docs} | {error,Errors,} when - Defs :: {Form,Line}, - Form :: _, - Line :: non_neg_integer(), - Cinfo :: #cinfo{}, - Docs :: doc(), - Errors :: nonempty_list({error,Line,Error}), - Error :: any(). - -extract_module_docs(Defs) -> %Just give a default #cinfo{} - extract_module_docs(Defs, #cinfo{}). - -extract_module_docs(, _Ci) -> {ok,}; -extract_module_docs(Defs, Ci) -> - {Mdoc,Docs} = do_forms(Defs), - Errors = filter(fun (#doc{}) -> false; - (_) -> true - end, Docs), - ?DEBUG("#doc: ~p\n", {Mdoc,Docs}, Ci#cinfo.opts), - ?IF( =:= Errors, - {ok,{Mdoc,Docs}}, - {error,Errors,}). - -do_forms(Fs) -> foldl(fun do_form/2, {,}, Fs). - -do_form({'define-module',_,Meta,Atts,_}, {Mdoc,Docs}) -> - {do_module_def(Meta, Atts, Mdoc),Docs}; -do_form({'extend-module',Meta,Atts,_}, {Mdoc,Docs}) -> - {do_module_def(Meta, Atts, Mdoc),Docs}; -do_form({'define-function',Name,Meta,Def,Line}, {Mdoc,Docs}) -> - {Mdoc,do_function(Name, Def, Meta, Line, Docs)}; -do_form({'define-macro',Name,Meta,Def,Line}, {Mdoc,Docs}) -> - {Mdoc,do_macro(Name, Def, Meta, Line, Docs)}; -do_form(_, Doc) -> Doc. %Ignore eval-when-compile - -do_module_def(Meta, Atts, Mdoc0) -> - Mdoc1 = collect_docs(Meta, Mdoc0), %First take meta docs - collect_docs(Atts, Mdoc1). %then the attribute docs - -collect_docs(As, Mdoc) -> - %% Collect all the docs in all the doc metas/attributes. - Afun = fun (doc|Docs, Md) -> - Dfun = fun (D, M) -> M ++ string_to_binary(D) end, - foldl(Dfun, Md, Docs); - (_, Md) -> Md - end, - foldl(Afun, Mdoc, As). - -do_function(Name, Def, Meta, Line, Docs) -> - %% Must get patterns and arity before we can check if excluded. - {Arity,Pats} = get_function_patterns(Def), - ?IF(exclude(Name, Arity, Meta), - Docs, - begin - Fdoc = make_function_doc(Name, Arity, Pats, Meta, Line), - Fdoc|Docs - end). - -do_macro(Name, Def, Meta, Line, Docs) -> - %% We only need the name to check for exclusion. - ?IF(exclude(Name, Meta), - Docs, - begin - Pats = get_macro_patterns(Def), - Mdoc = make_macro_doc(Name, Pats, Meta, Line), - Mdoc|Docs - end). - -%% exclude(Name, Arity, Meta) -> boolean(). -%% exclude(Name, Meta) -> boolean(). -%% Return true if a function should be excluded from the docs chunk. -%% $handle_undefined_function/2 needs special handling as it is -%% automatically generated but can also be defined by the user. So we -%% only include it is it has user documentation. - --spec exclude(Name, Arity, Meta) -> boolean() when - Name :: atom(), - Arity :: non_neg_integer(), - Meta :: list(). --spec exclude(Name, Meta) -> boolean() when - Name :: atom(), - Meta :: list(). - -exclude('LFE-EXPAND-EXPORTED-MACRO', 3, _) -> true; -exclude('$handle_undefined_function', 2, _) -> %Should check for doc string - true; -exclude(_, _, _) -> false. - -exclude('MODULE', _) -> true; -exclude(_, _) -> false. - -%% get_function_patterns(LambdaForm) -> {Arity,Patterns}. -%% get_macro_patterns(LambdaForm) -> Patterns. -%% Given a {match-,}lambda form, attempt to return its patterns (or -%% arglist). N.B. A guard is appended to its pattern and Patterns is -%% a list of lists. A macro definition must have two args, the pattern -%% and the environment. - --spec get_function_patterns(LambdaForm) -> {Arity,Patterns} when - LambdaForm :: nonempty_list(), - Arity :: non_neg_integer(), - Patterns :: nonempty_list({pattern(),guard()}). --spec get_macro_patterns(LambdaForm) -> Patterns when - LambdaForm :: nonempty_list(), - Patterns :: nonempty_list({pattern(),guard()}). - -get_function_patterns(lambda,Args|_) -> {length(Args),{Args,}}; -get_function_patterns('match-lambda',Pat|_=Cl|Cls) -> - {length(Pat),do_function_patterns(Cl|Cls, )}. - -do_function_patterns(Pat,'when'|Guard|_|Cls, Acc) -> - do_function_patterns(Cls, {Pat,Guard}|Acc); -do_function_patterns(Pat|_|Cls, Acc) -> - do_function_patterns(Cls, {Pat,}|Acc); -do_function_patterns(, Acc) -> reverse(Acc). - -get_macro_patterns(lambda,Args,_Env|_) -> Args; -get_macro_patterns('match-lambda'|Cls) -> do_macro_patterns(Cls, ). - -do_macro_patterns(Pat,_Env,'when'|Guard|_|Cls, Acc) -> - do_macro_patterns(Cls, {Pat,Guard}|Acc); -do_macro_patterns(Pat,_Env|_|Cls, Acc) -> - do_macro_patterns(Cls, {Pat,}|Acc); -do_macro_patterns(, Acc) -> reverse(Acc). - -%% make_function_doc(Name, Arity, Patterns, Doc, Line) -> doc(). -%% make_macro_doc(Name, Patterns, Doc, Line) -> doc(). -%% Convenience constructor for #doc{}, which is defined in src/lfe_doc.hrl. - --spec make_function_doc(Name, Arity, Patterns, Meta, Line) -> doc() when - Name :: atom(), - Arity :: non_neg_integer(), - Patterns :: {,}, - Meta :: any(), - Line :: pos_integer(). - --spec make_macro_doc(Name, Patterns, Meta, Line) -> doc() when - Name :: atom(), - Patterns :: {,}, - Meta :: any(), - Line :: pos_integer(). - -make_function_doc(Name, Arity, Patterns, Meta, Line) ->
View file
_service:tar_scm:lfe-1.3.tar.gz/src/lfe_doc.hrl
Deleted
@@ -1,42 +0,0 @@ -%% Copyright (c) 2016 Eric Bailey -%% -%% Licensed under the Apache License, Version 2.0 (the "License"); -%% you may not use this file except in compliance with the License. -%% You may obtain a copy of the License at -%% -%% http://www.apache.org/licenses/LICENSE-2.0 -%% -%% Unless required by applicable law or agreed to in writing, software -%% distributed under the License is distributed on an "AS IS" BASIS, -%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%% See the License for the specific language governing permissions and -%% limitations under the License. - -%% File : lfe_doc.hrl -%% Author : Eric Bailey -%% Purpose : Common documentation-related definitions. - -%% TODO: Actually define these, if possible. --type pattern() :: atom() | term(). - --type guard() :: term(). - --type name() :: atom() | {atom(),non_neg_integer()}. - -%% de{fun,macro} docs. --record(doc, {type = error(missing_type) :: function | macro, - exported = false :: boolean(), - name = error(missing_name) :: name(), - patterns = error(missing_patterns) :: {pattern(),guard()}, - doc = :: binary(), - line = error(missing_line) :: pos_integer() - }). - --type doc() :: #doc{}. - -%% For the BEAM beam chunk, "LDoc". --record(lfe_docs_v1, {docs = :: doc(), %Function/macro docs - moduledoc = :: binary() %Module doc - %% callback_docs=CallbackDocs, %Callback docs - %% type_docs=TypeDocs %Type docs - }).
View file
_service:tar_scm:lfe-1.3.tar.gz/src/lfe_pmod.erl
Deleted
@@ -1,282 +0,0 @@ -%% Copyright (c) 2008-2016 Robert Virding -%% -%% Licensed under the Apache License, Version 2.0 (the "License"); -%% you may not use this file except in compliance with the License. -%% You may obtain a copy of the License at -%% -%% http://www.apache.org/licenses/LICENSE-2.0 -%% -%% Unless required by applicable law or agreed to in writing, software -%% distributed under the License is distributed on an "AS IS" BASIS, -%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%% See the License for the specific language governing permissions and -%% limitations under the License. - -%% File : lfe_pmod.erl -%% Author : Robert Virding -%% Purpose : Lisp Flavoured Erlang parameterised module transformer. - --module(lfe_pmod). - --export(module/2). - -%% -compile(export_all). - --import(lists, member/2,keysearch/3, - all/2,map/2,foldl/3,foldr/3,mapfoldl/3,mapfoldr/3, concat/1). --import(ordsets, add_element/2,is_element/2,from_list/1,union/2). --import(orddict, store/3,find/2). - --import(lfe_env, new/0,add_vbinding/3,add_vbindings/2,get_vbinding/2, - add_fbinding/4,add_fbindings/2,get_fbinding/3, - add_ibinding/5,get_gbinding/3). - --include("lfe_comp.hrl"). - --define(Q(E), quote,E). %For quoting - --record(param, {mod=, %Module name - pars=, %Module parameters - extd=, %Extends - this=, %This match pattern - env=}). %Environment - -%% module(ModuleForms, CompInfo) -> {ModuleName,ModuleForms}. -%% Expand the forms to handle parameterised modules if necessary, -%% otherwise just pass forms straight through. - -module({'define-module',Mod|_|_,_}|_=Fs, Ci) -> - {Mod,expand_module(Fs, Ci#cinfo.opts)}; -module({'define-module',Mod|_,_}|_=Fs, _) -> - %% Normal module, do nothing. - {Mod,Fs}; -module(Fs, _) -> {,Fs}. %Not a module, do nothing - -expand_module(Fs0, Opts) -> - St0 = #param{env=lfe_env:new()}, - {Acc,St1} = lists:foldl(fun exp_form/2, {,St0}, Fs0), - Fs1 = lists:reverse(Acc), - ?DEBUG("#param: ~p\n", {Fs1,St1}, Opts), - %% {ok,_} = lfe_lint:module(Fs1, Opts), - Fs1. - -exp_form({'define-module',Mod|Ps,Meta,Atts0,L}, {Acc,St0}) -> - %% Save the good bits and define new/N and instance/N. - St1 = St0#param{mod=Mod,pars=Ps}, - {Atts1,St2} = exp_attrs(Atts0, St1), - {Nl,Il} = case St2#param.extd of - -> - {lambda,Ps,instance|Ps, - lambda,Ps,tuple,?Q(Mod)|Ps}; - Ex -> - {lambda,Ps,instance,call,?Q(Ex),?Q(new)|Ps|Ps, - lambda,base|Ps,tuple,?Q(Mod),base|Ps} - end, - New = 'define-function',new,,Nl, - Inst = 'define-function',instance,,Il, - %% Fix this match pattern depending on extends. - St3 = case St2#param.extd of - -> St2#param{this='=',this,tuple,'_'|Ps}; - _ -> St2#param{this='=',this,tuple,'_',base|Ps} - end, - {{{New,L},{Inst,L},'define-module',Mod,Meta,Atts1,L}|Acc,St3}; -exp_form({'define-function',F,Meta,Def0,L}, {Acc,St}) -> - Def1 = exp_function(Def0, St), - {{'define-function',F,Meta,Def1,L}|Acc,St}; -exp_form({F,L}, {Acc,St}) -> - {{F,L}|Acc,St}. - -exp_attrs(Atts0, St0) -> - %% Pre-scan to pick up 'extends'. - St1 = foldl(fun (extends,M, S) -> S#param{extd=M}; - (_, S) -> S - end, St0, Atts0), - %% Now do "real" processing. - {Atts1,St2} = mapfoldl(fun (export,all, S) -> {export,all,S}; - (export|Es0, S) -> - %% Add 1 for this to each export. - Es1 = map(fun (F,A) -> F,A+1 end, Es0), - {export|Es1,S}; - (import|Is, S0) -> - S1 = collect_imps(Is, S0), - {import|Is,S1}; - (Md, S) -> {Md,S} - end, St1, Atts0 ++ abstract,true), - %% Add export for new/N and instance/N. - Nar = length(St2#param.pars), - Iar = case St2#param.extd of - -> Nar; - _ -> Nar+1 - end, - {export,new,Nar,instance,Iar|Atts1,St2}. - -collect_imps(Is, St) -> - foldl(fun ('from',M|Fs, S) -> - Env = foldl(fun (F,Ar, E) -> - add_ibinding(M, F, Ar, F, E) end, - S#param.env, Fs), - S#param{env=Env}; - ('rename',M|Fs, S) -> - Env = foldl(fun (F,Ar,R, E) -> - add_ibinding(M, F, Ar, R, E) end, - S#param.env, Fs), - S#param{env=Env} - end, St, Is). - -%% exp_function(Lambda, State) -> Lambda. -%% The resultant code matches the arguments in two steps: first the -%% THIS arguemnt is matched and then the expanded function body -%% ((match-)lambda) is funcalled. We KNOW that funcall of a -%% (match-)lambda is inline expanded into a let or case so this is -%% efficient. - -exp_function(Lambda, #param{this=Th,env=Env}) -> - As = new_args(lambda_arity(Lambda)), - 'match-lambda',As ++ Th,funcall,exp_expr(Lambda, Env)|As. - -%% exp_function('match-lambda'|Cls0, #param{this=Th,env=Env}) -> -%% Cls1 = map(fun (As|Body) -> -%% exp_clause(As ++ Th|Body, Env) -%% end, Cls0), -%% 'match-lambda'|Cls1; -%% exp_function(lambda,As|Body0, #param{this=Th,env=Env}) -> -%% Body1 = exp_list(Body0, Env), -%% 'match-lambda',As ++ Th|Body1. - -new_args(N) when N > 0 -> - list_to_atom("{{-" ++ $a+N-1 ++ "-}}")|new_args(N-1); -new_args(0) -> . - -%% exp_expr(Sexpr, Environment) -> Expr. -%% Expand Sexpr. - -%% Handle the Core data special forms. -exp_expr(quote|_=E, _) -> E; -exp_expr(cons,H,T, Env) -> - cons,exp_expr(H, Env),exp_expr(T, Env); -exp_expr(car,E, Env) -> car,exp_expr(E, Env); %Provide lisp names -exp_expr(cdr,E, Env) -> cdr,exp_expr(E, Env); -exp_expr(list|Es, Env) -> list|exp_list(Es, Env); -exp_expr(tuple|Es, Env) -> tuple|exp_list(Es, Env); -exp_expr(tref|_,_=Es, Env) -> tref|exp_list(Es, Env); -exp_expr(tset|_,_,_=Es, Env) -> tset|exp_list(Es, Env); -exp_expr(binary|Bs, Env) -> - binary|exp_binary(Bs, Env); -%% Handle the Core closure special forms. -exp_expr(lambda|Body, Env) -> - lambda|exp_lambda(Body, Env); -exp_expr('match-lambda'|Cls, Env) -> - 'match-lambda'|exp_match_lambda(Cls, Env); -exp_expr('let'|Body, Env) -> - 'let'|exp_let(Body, Env); -exp_expr('let-function'|Body, Env) -> - 'let-function'|exp_let_function(Body, Env); -exp_expr('letrec-function'|Body, Env) -> - 'letrec-function'|exp_letrec_function(Body, Env); -%% Handle the control special forms. -exp_expr('progn'|Body, Env) -> - progn|exp_body(Body, Env); -exp_expr('if'|Body, Env) -> - 'if'|exp_if(Body, Env); -exp_expr('case'|Body, Env) -> - 'case'|exp_case(Body, Env); -exp_expr('receive'|Body, Env) -> - 'receive'|exp_receive(Body, Env); -exp_expr('catch'|Body, Env) -> - 'catch'|exp_body(Body, Env); -exp_expr('try'|Body, Env) -> - 'try'|exp_try(Body, Env); -exp_expr(funcall,F|As, Env) -> - funcall,exp_expr(F, Env)|exp_list(As, Env); -exp_expr(call|Body, Env) -> - call|exp_call(Body, Env); -exp_expr(Fun|Es, Env) when is_atom(Fun) -> - Ar = length(Es), - case get_fbinding(Fun, Ar, Env) of - {yes,_,_} -> Fun|exp_list(Es, Env); %Imported or Bif - {yes,local} -> Fun|exp_list(Es, Env); %Local function - _ -> Fun|exp_list(Es, Env) ++ this - end;
View file
_service:tar_scm:lfe-1.3.tar.gz/src/lfe_trans.erl
Deleted
@@ -1,935 +0,0 @@ -%% Copyright (c) 2008-2013 Robert Virding -%% -%% Licensed under the Apache License, Version 2.0 (the "License"); -%% you may not use this file except in compliance with the License. -%% You may obtain a copy of the License at -%% -%% http://www.apache.org/licenses/LICENSE-2.0 -%% -%% Unless required by applicable law or agreed to in writing, software -%% distributed under the License is distributed on an "AS IS" BASIS, -%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%% See the License for the specific language governing permissions and -%% limitations under the License. - -%% File : lfe_trans.erl -%% Author : Robert Virding -%% Purpose : Lisp Flavoured Erlang translator. - -%%% Translate LFE code to/from vanilla Erlang AST. -%%% -%%% Note that we don't really check code here as such, we assume the -%%% input is correct. If there is an error in the input we just fail. -%%% This allows us to accept forms which are actually illegal but we -%%% may special case, for example functions call in patterns which -%%% will become macro expansions. - --module(lfe_trans). - --export(from_expr/1,from_expr/2,from_body/1,from_body/2,from_lit/1, - to_expr/2,to_lit/2). - --import(lists, map/2,foldl/3,mapfoldl/3,foldr/3,splitwith/2). - --define(Q(E), quote,E). %We do a lot of quoting - --record(from, {vc=0 %Variable counter - }). - -%% from_expr(AST) -> Sexpr. -%% from_expr(AST, Variables) -> {Sexpr,Variables}. -%% from_body(AST) -> Sexpr. -%% from_body(AST, Variables) -> {Sexpr,Variables}. -%% Translate a vanilla Erlang expression into LFE. The main -%% difficulty is in the handling of variables. The implicit matching -%% of known variables in vanilla must be translated into explicit -%% equality tests in guards (which is what the compiler does -%% internally). For this we need to keep track of visible variables -%% and detect when they reused in patterns. - -from_expr(E) -> - {S,_,_} = from_expr(E, ordsets:new(), #from{}), - S. - -from_expr(E, Vs0) -> - Vt0 = ordsets:from_list(Vs0), %We are clean - {S,Vt1,_} = from_expr(E, Vt0, #from{}), - {S,ordsets:to_list(Vt1)}. - -from_body(Es) -> - {Les,_,_} = from_body(Es, ordsets:new(), #from{}), - progn|Les. - -from_body(Es, Vs0) -> - Vt0 = ordsets:from_list(Vs0), %We are clean - {Les,Vt1,_} = from_body(Es, Vt0, #from{}), - {progn|Les,ordsets:to_list(Vt1)}. - -%% from_expr(AST, VarTable, State) -> {Sexpr,VarTable,State}. - -from_expr({var,_,V}, Vt, St) -> {V,Vt,St}; %Unquoted atom -from_expr({nil,_}, Vt, St) -> {,Vt,St}; -from_expr({integer,_,I}, Vt, St) -> {I,Vt,St}; -from_expr({float,_,F}, Vt, St) -> {F,Vt,St}; -from_expr({atom,_,A}, Vt, St) -> {?Q(A),Vt,St}; %Quoted atom -from_expr({string,_,S}, Vt, St) -> {?Q(S),Vt,St}; %Quoted string -from_expr({cons,_,H,T}, Vt0, St0) -> - {Car,Vt1,St1} = from_expr(H, Vt0, St0), - {Cdr,Vt2,St2} = from_expr(T, Vt1, St1), - {from_cons(Car, Cdr),Vt2,St2}; -%% {cons,Car,Cdr,Vt2,St2}; -from_expr({tuple,_,Es}, Vt0, St0) -> - {Ss,Vt1,St1} = from_expr_list(Es, Vt0, St0), - {tuple|Ss,Vt1,St1}; -from_expr({bin,_,Segs}, Vt0, St0) -> - {Ss,Vt1,St1} = from_bitsegs(Segs, Vt0, St0), - {binary|Ss,Vt1,St1}; -from_expr({map,_,Assocs}, Vt0, St0) -> %Build a map - {Ps,Vt1,St1} = from_map_assocs(Assocs, Vt0, St0), - {map|Ps,Vt1,St1}; -from_expr({map,_,Map,Assocs}, Vt0, St0) -> %Update a map - {Lm,Vt1,St1} = from_expr(Map, Vt0, St0), - from_map_update(Assocs, nul, Lm, Vt1, St1); -%% Core closure special forms. -from_expr({'fun',_,{clauses,Cls}}, Vt, St0) -> - {Lcls,St1} = from_fun_cls(Cls, Vt, St0), - {'match-lambda'|Lcls,Vt,St1}; %Don't bother using lambda -from_expr({'fun',_,{function,F,A}}, Vt, St0) -> - %% Build a lambda. - {Vs,St1} = new_from_vars(A, St0), - {lambda,Vs,F|Vs,Vt,St1}; -from_expr({'fun',_,{function,M,F,A}}, Vt0, St0) -> - %% Translate to call to erlang:make_fun/3. - {Las,Vt1,St1} = from_expr_list(M,F,A, Vt0, St0), - {call,?Q(erlang),?Q(make_fun)|Las,Vt1,St1}; -%% Core control special forms. -from_expr({block,_,Es}, Vt0, St0) -> - {Les,Vt1,St1} = from_body(Es, Vt0, St0), - {progn|Les,Vt1,St1}; -from_expr({'case',_,E,Cls}, Vt0, St0) -> - {Le,Vt1,St1} = from_expr(E, Vt0, St0), - {Lcls,Vt2,St2} = from_icrt_cls(Cls, Vt1, St1), - {'case',Le|Lcls,Vt2,St2}; -from_expr({'if',_,Cls}, Vt0, St0) -> - {Lcls,Vt1,St1} = from_icrt_cls(Cls, Vt0, St0), - {'case',|Lcls,Vt1,St1}; -from_expr({'receive',_,Cls}, Vt0, St0) -> - {Lcls,Vt1,St1} = from_icrt_cls(Cls, Vt0, St0), - {'receive'|Lcls,Vt1,St1}; -from_expr({'receive',_,Cls,Timeout,Body}, Vt0, St0) -> - {Lcls,Vt1,St1} = from_icrt_cls(Cls, Vt0, St0), - {Lt,Vt2,St2} = from_expr(Timeout, Vt1, St1), - {Lb,Vt3,St3} = from_body(Body, Vt2, St2), - {'receive'|Lcls ++ 'after',Lt|Lb,Vt3,St3}; -%% More complex special forms. These become LFE macros. -from_expr({lc,_,E,Qs}, Vt0, St0) -> - {Lqs,Vt1,St1} = from_lc_quals(Qs, Vt0, St0), - {Le,Vt2,St2} = from_expr(E, Vt1, St1), - {lc,Lqs,Le,Vt2,St2}; -from_expr({record,_,R,Fs}, Vt0, St0) -> %Create a record - MR = list_to_atom("make-" ++ atom_to_list(R)), - {Lfs,Vt1,St1} = from_rec_fields(Fs, Vt0, St0), - {MR|Lfs,Vt1,St1}; -from_expr({record,_,E,R,Fs}, Vt0, St0) -> %Set fields in record - SR = list_to_atom("set-" ++ atom_to_list(R)), - {Le,Vt1,St1} = from_expr(E, Vt0, St0), - {Lfs,Vt2,St2} = from_rec_fields(Fs, Vt1, St1), - {SR,Le|Lfs,Vt2,St2}; -from_expr({record_field,_,E,R,{atom,_,F}}, Vt0, St0) -> %We KNOW! - RF = list_to_atom(atom_to_list(R) ++ "-" ++ atom_to_list(F)), - {Le,Vt1,St1} = from_expr(E, Vt0, St0), - {RF,Le,Vt1,St1}; -from_expr({record_field,_,_,_}=M, Vt, St) -> %Pre R16 packages - from_package_module(M, Vt, St); -%% Function calls. -from_expr({call,_,{remote,_,M,F},As}, Vt0, St0) -> %Remote function call - {Lm,Vt1,St1} = from_expr(M, Vt0, St0), - {Lf,Vt2,St2} = from_expr(F, Vt1, St1), - {Las,Vt3,St3} = from_expr_list(As, Vt2, St2), - {call,Lm,Lf|Las,Vt3,St3}; -from_expr({call,_,{atom,_,F},As}, Vt0, St0) -> %Local function call - {Las,Vt1,St1} = from_expr_list(As, Vt0, St0), - {F|Las,Vt1,St1}; -from_expr({call,_,F,As}, Vt0, St0) -> %F not an atom or remote - {Lf,Vt1,St1} = from_expr(F, Vt0, St0), - {Las,Vt2,St2} = from_expr_list(As, Vt1, St1), - {funcall,Lf|Las,Vt2,St2}; -from_expr({'try',_,Es,Scs,Ccs,As}, Vt, St0) -> - %% Currently erl_lint does not allow any exports! - {Les,_,St1} = from_body(Es, Vt, St0), - %% These maybe empty. - {Lscs,_,St2} = if Scs =:= -> {,,St1}; - true -> from_icrt_cls(Scs, Vt, St1) - end, - {Lccs,_,St3} = if Ccs =:= -> {,,St2}; - true -> from_icrt_cls(Ccs, Vt, St2) - end, - {Las,_,St4} = from_body(As, Vt, St3), - {'try',progn|Les| - from_maybe('case', Lscs) ++ - from_maybe('catch', Lccs) ++ - from_maybe('after', Las),Vt,St4}; -from_expr({'catch',_,E}, Vt0, St0) -> - {Le,Vt1,St1} = from_expr(E, Vt0, St0), - {'catch',Le,Vt1,St1}; -from_expr({match,L,P,E}, Vt0, St0) -> - {Alias,St1} = new_from_var(St0), %Alias variable value - MP = {match,L,{var,L,Alias},P}, - {Lp,Eqt,Vt1,St2} = from_pat(MP, Vt0, St1), %The alias pattern - {Le,Vt2,St3} = from_expr(E, Vt1, St2), %The expression - Leg = from_eq_tests(Eqt), %Implicit guard tests - {'let',Lp,'when'|Leg,Le,Alias,Vt2,St3}; -from_expr({op,_,Op,A}, Vt0, St0) -> - {La,Vt1,St1} = from_expr(A, Vt0, St0), - {Op,La,Vt1,St1}; -from_expr({op,_,Op,L,R}, Vt0, St0) -> - {Ll,Vt1,St1} = from_expr(L, Vt0, St0), - {Lr,Vt2,St2} = from_expr(R, Vt1, St1), - {Op,Ll,Lr,Vt2,St2}. - -from_cons(Car, list|Es) -> list,Car|Es; -from_cons(Car, ) -> list,Car; -from_cons(Car, Cdr) -> cons,Car,Cdr. - -%% from_body(Expressions, VarTable, State) -> {Body,VarTable,State}. -%% Handle '=' specially here and translate into let containing rest -%% of body. - -from_body({match,_,_,_}=Match, Vt0,St0) -> %Last match - {Lm,Vt1,St1} = from_expr(Match, Vt0, St0), %Must return pattern as value
View file
_service:tar_scm:lfe-1.3.tar.gz/test/prop_lfe_doc.erl
Deleted
@@ -1,161 +0,0 @@ -%% Copyright (c) 2016 Eric Bailey -%% -%% Licensed under the Apache License, Version 2.0 (the "License"); -%% you may not use this file except in compliance with the License. -%% You may obtain a copy of the License at -%% -%% http://www.apache.org/licenses/LICENSE-2.0 -%% -%% Unless required by applicable law or agreed to in writing, software -%% distributed under the License is distributed on an "AS IS" BASIS, -%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -%% See the License for the specific language governing permissions and -%% limitations under the License. - -%% File : prop_lfe_doc.erl -%% Author : Eric Bailey -%% Purpose : PropEr tests for the lfe_doc module. - --module(prop_lfe_doc). - --export(prop_define_lambda/0,prop_define_match/0). - --include_lib("proper/include/proper.hrl"). - -%%%=================================================================== -%%% Properties -%%%=================================================================== - -prop_define_lambda() -> ?FORALL(Def, define_lambda(), validate(Def)). - -prop_define_match() -> ?FORALL(Def, define_match(), validate(Def)). - -validate({'define-function',Name,_Doc,Def,_}=Func) -> - validate_function(Name, function_arity(Def), Func); -validate({'define-macro',Name,_Doc,_Def,_}=Mac) -> - validate_macro(Name, Mac). - -function_arity(lambda,Args|_) -> length(Args); -function_arity('match-lambda',Pat|_|_) -> length(Pat). - -validate_function(Name, Arity, {_Define,_Name,Meta,_Def,Line}=Func) -> - case lfe_doc:extract_module_docs(Func) of - {ok,{,Fdoc}} -> - (lfe_doc:collect_docs(Meta, ) =:= lfe_doc:function_doc(Fdoc)) - and (Name =:= lfe_doc:function_name(Fdoc)) - and (Arity =:= lfe_doc:function_arity(Fdoc)) - and (Line =:= lfe_doc:function_line(Fdoc)); - _ -> false - end. - -validate_macro(Name, {_Define,_Name,Meta,_Lambda,Line}=Mac) -> - case lfe_doc:extract_module_docs(Mac) of - {ok,{,Mdoc}} -> - (lfe_doc:collect_docs(Meta, ) =:= lfe_doc:macro_doc(Mdoc)) - and (Name =:= lfe_doc:macro_name(Mdoc)) - and (Line =:= lfe_doc:macro_line(Mdoc)); - _ -> false - end. - -%%%=================================================================== -%%% Definition shapes -%%%=================================================================== - -define_lambda() -> - {'define-function',atom1(),meta_with_doc(),lambda(),line()}. - -define_match() -> - ?LET(D, define(), {D,atom1(),meta_with_doc(),'match-lambda'(D),line()}). - - -%%%=================================================================== -%%% Custom types -%%%=================================================================== - -%%% Definitions - -define() -> oneof('define-function','define-macro'). - -lambda() -> lambda,arglist_simple()|body(). - -'match-lambda'('define-function') -> - 'match-lambda'|non_empty(list(function_pattern_clause())); -'match-lambda'('define-macro') -> - 'match-lambda'|non_empty(list(macro_pattern_clause())). - -arglist_simple() -> list(atom1()). - -atom1() -> oneof(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z,''). - -body() -> non_empty(list(form())). - -form() -> union(form_elem(),atom1()|list(form_elem())). - -form_elem() -> union(non_string_term(),printable_string(),atom1()). - -meta_with_doc() -> doc,docstring(). - -docstring() -> printable_string(). - -line() -> pos_integer(). - - -%%% Patterns - -pattern() -> union(non_string_term(),printable_string(),pattern_form()). - -pattern_form() -> - oneof('=','++*',, - backquote,quote, - binary,cons,list,map,tuple, - match_fun()) - | body(). - -match_fun() -> 'match-record'. - -macro_pattern_clause() -> pattern_clause(rand_arity(), true). - -function_pattern_clause() -> pattern_clause(rand_arity(), false). - -pattern_clause(Arity, Macro) -> - arglist_patterns(Arity, Macro)|oneof(guard(),form())|body(). - -arglist_patterns(Arity, false) -> vector(Arity, pattern()); -arglist_patterns(Arity, true) -> vector(Arity, pattern()),'$ENV'. - -guard() -> 'when'|non_empty(list(union(logical_clause(),comparison()))). - - -%%% Logical clauses - -logical_clause() -> - X = union(atom1(),comparison()), - logical_operator(),X|non_empty(list(X)). - -logical_operator() -> oneof('and','andalso','or','orelse'). - - -%%% Comparisons - -comparison() -> comparison_operator(),atom1()|list(atom1()). - -comparison_operator() -> oneof('==','=:=','=/=','<','>','=<','>='). - - -%%% Strings and non-strings - -non_string_term() -> - union(atom1(),number(),,bitstring(),binary(),boolean(),tuple()). - -printable_char() -> union(integer(32, 126),integer(160, 255)). - -printable_string() -> list(printable_char()). - - -%%% Rand compat - --ifdef(NEW_RAND). -rand_arity() -> rand:uniform(10). --else. -rand_arity() -> random:uniform(10). --endif.
View file
_service:tar_scm:lfe-2.1.1.tar.gz/.github
Added
+(directory)
View file
_service:tar_scm:lfe-2.1.1.tar.gz/.github/workflows
Added
+(directory)
View file
_service:tar_scm:lfe-2.1.1.tar.gz/.github/workflows/cicd.yml
Added
@@ -0,0 +1,113 @@ +name: ci/cd + +on: + workflow_dispatch: + push: + branches: master, release/*, task/*, feature/*, bugfix/*, develop + pull_request: + branches: master, release/*, task/*, feature/*, bugfix/*, develop + +jobs: + + builds: + name: Newer builds - OTP ${{ matrix.otp-version }} / ${{ matrix.os }} + runs-on: ubuntu-latest + + strategy: + fail-fast: false + matrix: + otp-version: '22', '23', '24', '25' + os: 'ubuntu-latest' + + container: + image: erlang:${{ matrix.otp-version }} + + steps: + - uses: actions/checkout@v2 + - name: Erlang version check + run: erl -noshell -eval 'erlang:display(erlang:system_info(system_version))' -eval 'init:stop()' + - name: Rebar version check + run: rebar3 -v + - name: Compile (with rebar3) + run: rebar3 compile + - name: Run eunit Tests + run: make eunit + - name: Run proper Tests + run: make proper + - name: CT Suite Tests + run: make ct + + installs: + name: Newer installs - OTP ${{ matrix.otp-version }} / ${{ matrix.os }} + needs: builds + runs-on: ubuntu-latest + + strategy: + fail-fast: false + matrix: + otp-version: '22', '23', '24', '25' + os: 'ubuntu-latest' + + container: + image: erlang:${{ matrix.otp-version }} + + steps: + - uses: actions/checkout@v2 + - name: Erlang version check + run: erl -noshell -eval 'erlang:display(erlang:system_info(system_version))' -eval 'init:stop()' + - name: Compile (with make) + run: make compile + - name: Install + run: make install PREFIX=$(mktemp -d) + + + older-builds: + name: Older builds - OTP ${{ matrix.otp-version }} / ${{ matrix.os }} + runs-on: ubuntu-18.04 + + strategy: + fail-fast: false + matrix: + otp-version: '19', '20', '21' + os: 'ubuntu-18.04' + + container: + image: erlang:${{ matrix.otp-version }} + + steps: + - uses: actions/checkout@v2 + - name: Erlang version check + run: erl -noshell -eval 'erlang:display(erlang:system_info(system_version))' -eval 'init:stop()' + - name: Rebar version check + run: rebar3 -v + - name: Compile (with rebar3) + run: rebar3 compile + - name: Run eunit Tests + run: make eunit + - name: Run proper Tests + run: make proper + - name: CT Suite Tests + run: make ct + + older-installs: + name: Older installs - OTP ${{ matrix.otp-version }} / ${{ matrix.os }} + needs: older-builds + runs-on: ubuntu-18.04 + + strategy: + fail-fast: false + matrix: + otp-version: '19', '20', '21' + os: 'ubuntu-18.04' + + container: + image: erlang:${{ matrix.otp-version }} + + steps: + - uses: actions/checkout@v2 + - name: Erlang version check + run: erl -noshell -eval 'erlang:display(erlang:system_info(system_version))' -eval 'init:stop()' + - name: Compile (with make) + run: make compile + - name: Install + run: make install PREFIX=$(mktemp -d)
View file
_service:tar_scm:lfe-1.3.tar.gz/.gitignore -> _service:tar_scm:lfe-2.1.1.tar.gz/.gitignore
Changed
@@ -15,3 +15,8 @@ doc/pdf/* ebin/* erl_crash.dump +*~ +\#*\# +.\#* +.emacs.desktop +.emacs.desktop.lock \ No newline at end of file
View file
_service:tar_scm:lfe-1.3.tar.gz/Dockerfile -> _service:tar_scm:lfe-2.1.1.tar.gz/Dockerfile
Changed
@@ -1,44 +1,13 @@ -# Base image +# LFE Docker images are now based entirely upon the official Erlang Docker +# images which include both Debian and Alpine images. # -# VERSION 0.2 -FROM debian:latest -MAINTAINER LFE Maintainers <maintainers@lfe.io> - -ENV DEBIAN_FRONTEND noninteractive -RUN apt-get update -RUN apt-get install -y --no-install-recommends \ - apt-utils \ - build-essential -RUN apt-get install -y --no-install-recommends \ - ca-certificates \ - libcurl4-openssl-dev \ - curl \ - wget \ - git -RUN apt-get install -y --no-install-recommends \ - libsctp1 libsctp-dev lksctp-tools -RUN apt-get install -y --no-install-recommends \ - pandoc - -ENV ERLANG_DEB1 erlang-solutions_1.0_all.deb -ENV ERLANG_DEB2 esl-erlang_19.1.3-1~debian~jessie_amd64.deb -ENV ERLANG_HOST https://packages.erlang-solutions.com -ENV ERLANG_PATH erlang/esl-erlang/FLAVOUR_1_general -RUN curl -L -O $ERLANG_HOST/$ERLANG_DEB1 -RUN dpkg -i $ERLANG_DEB1 && rm $ERLANG_DEB1 -RUN apt-get update -RUN curl -L -O $ERLANG_HOST/$ERLANG_PATH/$ERLANG_DEB2 -RUN dpkg -i --force-depends $ERLANG_DEB2 && rm $ERLANG_DEB2 - -ENV REBAR_REPO https://github.com/rebar/rebar.git -RUN git clone $REBAR_REPO && cd rebar && \ - git checkout tags/2.6.0 && \ - ./bootstrap && \ - cp rebar /usr/local/bin - -ADD . /opt/erlang/lfe -RUN cd /opt/erlang/lfe && make install - -ENV ERL_LIBS=$ERL_LIBS:/opt/erlang/lfe -ENV DEBIAN_FRONTEND "" -CMD /usr/bin/lfe -eval "(io:format \"~p~n\" (list (* 2 (lists:foldl #'+/2 0 (lists:seq 1 6)))))" +# Resources: +# * Erlang images: https://hub.docker.com/_/erlang +# * LFE images: https://hub.docker.com/r/lfex/lfe/tags +# * LFE Dockerfiles repo: https://github.com/lfex/dockerfiles +# +# Note: The last link has lots of usage examples in the README file. +# Note: The latest version is an image which contains the most recently +# released LFE and Erlang versions. +# +FROM lfex/lfe:latest
View file
_service:tar_scm:lfe-1.3.tar.gz/Makefile -> _service:tar_scm:lfe-2.1.1.tar.gz/Makefile
Changed
@@ -1,4 +1,4 @@ -# Copyright (c) 2016 Robert Virding +# Copyright (c) 2016-2020 Robert Virding # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -21,25 +21,26 @@ LSRCDIR = src INCDIR = include EMACSDIR = emacs +HOSTCC ?= $(CC) PREFIX ?= /usr/local INSTALL = install INSTALL_DIR = $(INSTALL) -m755 -d INSTALL_DATA = $(INSTALL) -m644 INSTALL_BIN = $(INSTALL) -m755 DESTLIBDIR := $(PREFIX)/lib/lfe +DESTINCDIR := $(DESTLIBDIR)/$(INCDIR) DESTEBINDIR := $(DESTLIBDIR)/$(EBINDIR) DESTBINDIR := $(DESTLIBDIR)/$(BINDIR) VPATH = $(SRCDIR) -MKDIR_P = mkdir -p MANDB = $(shell which mandb) -ERLCFLAGS = -W1 -ERLC = erlc +ERLCFLAGS = -W1 +debug_info +ERLC ?= erlc -LFECFLAGS = -pa ../lfe -LFEC = $(BINDIR)/lfe $(BINDIR)/lfec +LFECFLAGS = -pa ../lfe +debug-info +LFEC = $(BINDIR)/lfescript $(BINDIR)/lfec APP_DEF = lfe.app LIB=lfe @@ -72,10 +73,10 @@ .SUFFIXES: .erl .beam $(BINDIR)/%: $(CSRCDIR)/%.c - cc -o $@ $< + $(HOSTCC) -o $@ $< $(EBINDIR)/%.beam: $(SRCDIR)/%.erl - @$(MKDIR_P) $(EBINDIR) + @$(INSTALL_DIR) $(EBINDIR) $(ERLC) -I $(INCDIR) -o $(EBINDIR) $(COMP_OPTS) $(ERLCFLAGS) $< %.erl: %.xrl @@ -89,7 +90,7 @@ all: compile -.PHONY: compile erlc-compile lfec-compile erlc-lfec emacs install docs clean docker-build docker-push docker update-mandb +.PHONY: compile erlc-compile lfec-compile erlc-lfec emacs install install-beam install-bin install-man docs clean docker-build docker-push docker update-mandb compile: comp_opts.mk $(MAKE) $(MFLAGS) erlc-lfec @@ -117,17 +118,30 @@ -include comp_opts.mk -$(BINDIR)/lfe%: - $(INSTALL_BIN) $@ $(DESTBINDIR) +install: compile install-include install-beam install-bin install-man -install: compile install-man +install-include: + $(INSTALL_DIR) $(DESTINCDIR) + $(INSTALL_DATA) $(INCDIR)/* $(DESTINCDIR) + +install-beam: rm -Rf $(DESTEBINDIR) $(INSTALL_DIR) $(DESTEBINDIR) - $(INSTALL_DATA) $(EBINDIR)/$(APP_DEF) $(DESTEBINDIR) - $(INSTALL_DATA) $(addprefix $(EBINDIR)/, $(EBINS)) $(DESTEBINDIR) - $(INSTALL_DATA) $(addprefix $(EBINDIR)/, $(LBINS)) $(DESTEBINDIR) + $(INSTALL_DATA) \ + $(EBINDIR)/$(APP_DEF) \ + $$(printf '%s\n' $(addprefix $(EBINDIR)/, $(EBINS)) | sort -u) \ + $(addprefix $(EBINDIR)/, $(LBINS)) \ + $(DESTEBINDIR) + +install-bin: $(INSTALL_DIR) $(DESTBINDIR) - $(MAKE) $(BINDIR)/lfe $(BINDIR)/lfec $(BINDIR)/lfedoc $(BINDIR)/lfescript + $(INSTALL_BIN) \ + $(BINDIR)/lfe \ + $(BINDIR)/lfec \ + $(BINDIR)/lfedoc \ + $(BINDIR)/lfescript \ + $(DESTBINDIR) + $(INSTALL_DIR) $(PREFIX)/bin ln -sf $(DESTBINDIR)/* $(PREFIX)/bin/ clean: @@ -152,6 +166,33 @@ regenerate-parser: erl -noshell -eval 'spell1:file("src/lfe_parse", report,verbose,{outdir,"./src/"},{includefile,code:lib_dir(spell1,include) ++ "/spell1inc.hrl"}), init:stop().' +############### +### TESTING ### +############### + +# XXX for some reason, the first pass of eunit doesn't run the tests?! +eunit: + @rebar3 as test do compile,eunit,eunit + +# XXX We've had to limit 'n' to 20, since the default count of 100 was +# causing VM crashes due to atom-table filling. Note, however: +# * 'prop_lfe_docs:prop_define_lambda' works just fine with 100 tests +# * 'prop_lfe_docs:prop_define_match' is the one that crashes the VM +proper: + @rebar3 as test do compile,proper -n 20 + +common-test: + @rebar3 as test do compile,ct + +ct: common-test + +tests: + @rebar3 as test do compile,eunit,eunit,proper -n 20,ct + +##################### +### DOCUMENTATION ### +##################### + # Targets for generating docs and man pages DOCDIR = doc DOCSRC = $(DOCDIR)/src @@ -211,16 +252,16 @@ $(DOCDIR)/%.txt: export GROFF_NO_SGR=1 $(DOCDIR)/%.txt: $(MANDIR)/%.1 - groff -t -e -mandoc -Tutf8 -Kutf8 $< | col -bx > $@ + groff -t -e -mandoc -Tutf8 $< | col -bx > $@ $(DOCDIR)/%.txt: $(MANDIR)/%.3 - groff -t -e -mandoc -Tutf8 -Kutf8 $< | col -bx > $@ + groff -t -e -mandoc -Tutf8 $< | col -bx > $@ $(DOCDIR)/%.txt: $(MANDIR)/%.7 - groff -t -e -mandoc -Tutf8 -Kutf8 $< | col -bx > $@ + groff -t -e -mandoc -Tutf8 $< | col -bx > $@ $(PDFDIR): - @$(MKDIR_P) $(PDFDIR) + @$(INSTALL_DIR) $(PDFDIR) docs-pdf: $(PDFDIR) \ $(addprefix $(PDFDIR)/, $(PDF1S)) \ @@ -228,16 +269,16 @@ $(addprefix $(PDFDIR)/, $(PDF7S)) $(PDFDIR)/%.pdf: $(DOCSRC)/%.1.md - pandoc -f markdown --latex-engine=xelatex -o $@ $< + pandoc -f markdown --pdf-engine=xelatex -o $@ $< $(PDFDIR)/%.pdf: $(DOCSRC)/%.3.md - pandoc -f markdown --latex-engine=xelatex -o $@ $< + pandoc -f markdown --pdf-engine=xelatex -o $@ $< $(PDFDIR)/%.pdf: $(DOCSRC)/%.7.md - pandoc -f markdown --latex-engine=xelatex -o $@ $< + pandoc -f markdown --pdf-engine=xelatex -o $@ $< $(EPUBDIR): - @$(MKDIR_P) $(EPUBDIR) + @$(INSTALL_DIR) $(EPUBDIR) docs-epub: $(EPUBDIR) \ $(addprefix $(EPUBDIR)/, $(EPUB1S)) \ @@ -254,7 +295,7 @@ pandoc -f markdown -t epub -o $@ $< $(MANINSTDIR)/man%: - @$(MKDIR_P) -p $@ + @$(INSTALL_DIR) $@ ifeq (,$(findstring mandb,$(MANDB))) install-man: $(MANINSTDIR)/man1 $(MANINSTDIR)/man3 $(MANINSTDIR)/man7 @@ -290,6 +331,3 @@ docker-docs-bash: docker run -i -v `pwd`/doc:/docs -t lfex/lfe-docs:latest bash -travis: - @rebar3 ct - @rebar3 eunit -m clj-tests,prop_lfe_doc
View file
_service:tar_scm:lfe-1.3.tar.gz/README.md -> _service:tar_scm:lfe-2.1.1.tar.gz/README.md
Changed
@@ -1,6 +1,6 @@ # LFE -!Travis(https://img.shields.io/travis/rvirding/lfe.svg)(https://travis-ci.org/rvirding/lfe) +!Build Status(https://github.com/lfe/lfe/workflows/ci%2Fcd/badge.svg)(https://github.com/lfe/lfe/actions) !Hex.pm version(https://img.shields.io/hexpm/v/lfe.svg)(https://hex.pm/packages/lfe) !Hex.pm downloads(https://img.shields.io/hexpm/dt/lfe.svg)(https://hex.pm/packages/lfe) !Hex.pm weekly downloads(https://img.shields.io/hexpm/dw/lfe.svg)(https://hex.pm/packages/lfe) @@ -16,7 +16,7 @@ To compile LFE, simple clone it and compile: ```shell -$ git clone https://github.com/rvirding/lfe.git +$ git clone https://github.com/lfe/lfe.git $ cd lfe $ make compile ``` @@ -163,3 +163,9 @@ the docs, you'll want to read the instructions here: * Updating LFE Documentation(doc/src/updating_docs.md) + +## Join the Community + +LFE on Slack(https://lfe.slack.com), join by requesting an invite here(https://erlef.org/slack-invite/lfe) + +LFE Forum - Erlang Forums(https://erlangforums.com/lfe)
View file
_service:tar_scm:lfe-1.3.tar.gz/VERSION -> _service:tar_scm:lfe-2.1.1.tar.gz/VERSION
Changed
@@ -1,1 +1,1 @@ -1.3 +2.1.1
View file
_service:tar_scm:lfe-1.3.tar.gz/bin/lfe -> _service:tar_scm:lfe-2.1.1.tar.gz/bin/lfe
Changed
@@ -1,5 +1,5 @@ #! /bin/sh -# Copyright (c) 2008-2014 Robert Virding +# Copyright (c) 2008-2020 Robert Virding # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -52,13 +52,13 @@ # First step over the flag section adding them to the end. while "$i" -gt 0 ; do case "$1" in - -e | -eval) # We are going to eval + -e | -eval | -lfe_eval) # We are going to eval e="-lfe_eval" - break ;; # delay removing this + break ;; # delay removing this -h | --help) - $(show_help) # Show help + $(show_help) # Show help exit 1 ;; - -extra | --) # We are explicitly done + -extra | --) # We are explicitly done shift ; i=`expr $i - 1` break ;; -* | +*) # Flags
View file
_service:tar_scm:lfe-1.3.tar.gz/bin/lfe-first-try -> _service:tar_scm:lfe-2.1.1.tar.gz/bin/lfe-first-try
Changed
@@ -1,5 +1,5 @@ #!/bin/sh -# Copyright (c) 2008-2014 Robert Virding +# Copyright (c) 2008-2020 Robert Virding # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License.
View file
_service:tar_scm:lfe-1.3.tar.gz/bin/lfe-test -> _service:tar_scm:lfe-2.1.1.tar.gz/bin/lfe-test
Changed
@@ -1,5 +1,5 @@ #!/bin/sh -# Copyright (c) 2008-2014 Robert Virding +# Copyright (c) 2008-2020 Robert Virding # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License.
View file
_service:tar_scm:lfe-1.3.tar.gz/bin/lfec -> _service:tar_scm:lfe-2.1.1.tar.gz/bin/lfec
Changed
@@ -1,6 +1,6 @@ -#! /usr/bin/env lfe -;; -*- mode: lfe; -*- -;; Copyright (c) 2008-2014 Robert Virding. +#! /usr/bin/env lfescript +;; -*- mode: lfe -*- +;; Copyright (c) 2008-2020 Robert Virding. ;; ;; Licensed under the Apache License, Version 2.0 (the "License"); ;; you may not use this file except in compliance with the License. @@ -39,14 +39,16 @@ (parse-opts as (cons 'debug-print opts))) ((cons "-Werror" as) opts (parse-opts as (cons 'warnings-as-errors opts))) - ((cons (++* "-W" _) as) opts ;Ignore this here + ((cons (++ "-W" _) as) opts ;Ignore this here (parse-opts as opts)) ((cons "-D" as) opts (parse-opts as (cons 'debug-print opts))) ((cons "-E" as) opts - (parse-opts as (cons 'to-exp opts))) + (parse-opts as (cons 'to-expand opts))) ((cons "-L" as) opts (parse-opts as (cons 'to-lint opts))) + ((cons "-A" as) opts + (parse-opts as (cons 'to-erlang opts))) ((cons "-S" as) opts (parse-opts as (cons 'to-asm opts))) ((cons "-P" as) opts ;Ignore as no LFE counterpart @@ -61,7 +63,7 @@ (defun usage () (let ((usage (++ "Usage: lfec options file ...\n\n" - "Options:\n" + "Options:\n\n" "-h Print usage and exit\n" "-I name Name of include directory\n" "-o name Name of output directory\n" @@ -71,14 +73,17 @@ "-Werror Make all warnings into errors\n" "-Wnumber Set warning level (ignored)\n" "-D Equivalent to +debug-print\n" + "-E Equivalent to +to-expand\n" "-L Equivalent to +to-lint\n" - "-E Equivalent to +to-exp\n" + "-A Equivalent to +to-erlang\n" "-S Equivalent to +to-asm\n" "-- No more options, only file names follow\n" "+term Term will be added to options\n\n" "Terms include:\n\n" - "+binary, +no-docs, +to-exp, +to-lint, +to-core0, +to-core, +to-kernel, +to-asm\n" - "+{outdir, Dir}, +report, +return, +debug-print\n"))) + "+binary, +no-docs, +to-exp, +to-lint, +to-core0, +to-core, +to-kernel,\n" + "+to-asm, +{outdir, Dir}, +report, +return, +debug-print\n\n" + "Example:\n\n" + "$ lfec -I include -o ebin examples/ring.lfe\n\n"))) (io:put_chars usage))) (defun compile-file (file opts) @@ -96,11 +101,12 @@ (() _ 'ok)) ;; Parse the arguments and compile the files. -(case script-args - (() (usage)) - (as0 - (fix-code-path) - (let ((`#(,files ,opts1) (parse-opts as0 ()))) - (case (compile-files files (list* 'verbose 'report opts1)) - ('error (halt 1)) - ('ok 'ok))))) +(defun main (script-args) + (case script-args + (() (usage)) + (as0 + (fix-code-path) + (let ((`#(,files ,opts1) (parse-opts as0 ()))) + (case (compile-files files (list* 'verbose 'report opts1)) + ('error (halt 1)) + ('ok 'ok))))))
View file
_service:tar_scm:lfe-1.3.tar.gz/bin/lfedoc -> _service:tar_scm:lfe-2.1.1.tar.gz/bin/lfedoc
Changed
@@ -1,6 +1,6 @@ #!/usr/bin/env lfe ;; -*- mode: lfe; -*- -;; Copyright (c) 2016 Eric Bailey. +;; Copyright (c) 2016-2020 Eric Bailey. ;; ;; Licensed under the Apache License, Version 2.0 (the "License"); ;; you may not use this file except in compliance with the License. @@ -41,7 +41,7 @@ (parse-opts as (cons 'debug-print opts))) ((cons "-Werror" as) opts (parse-opts as (cons 'warnings-as-errors opts))) - ((cons (++* "-W" _) as) opts ;Ignore this here + ((cons (++ "-W" _) as) opts ;Ignore this here (parse-opts as opts)) ((cons "-D" as) opts (parse-opts as (cons 'debug-print opts))) @@ -49,7 +49,7 @@ (parse-opts as opts)) ((cons "--" as) opts (tuple as opts)) - ((cons (++* "+to" _) as) opts ;Ignore this here + ((cons (++ "+to" _) as) opts ;Ignore this here (parse-opts as opts)) ((cons (cons #\+ s) as) opts (let ((`#(ok ,t) (lfe_io:read_string s)))
View file
_service:tar_scm:lfe-1.3.tar.gz/bin/lfescript -> _service:tar_scm:lfe-2.1.1.tar.gz/bin/lfescript
Changed
@@ -1,5 +1,5 @@ #! /bin/sh -# Copyright (c) 2008-2015 Robert Virding +# Copyright (c) 2008-2020 Robert Virding # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -121,7 +121,14 @@ # The following works for rebar and erl.mk PROJ_LIBS=$(find_libs "./deps") # The following works for rebar3 -R3_PROJ_LIBS=$(find_libs "./_build/${REBAR_PROFILE:-default}/deps"):$(find_libs "./_build/${REBAR_PROFILE:-default}/lib") +if -d "$REBAR_DEPS_DIR" ; then + # Use $REBAR_DEPS_DIR if set... + R3_PROJ_LIBS=$(find_libs "$REBAR_DEPS_DIR") +else + # ... otherwise provide a sensible default + R3_PROJ_LIBS=$(find_libs "./_build/${REBAR_PROFILE:-default}/deps"):$(find_libs "./_build/${REBAR_PROFILE:-default}/lib") +fi LFE_HOME_LIBS=$(find_libs "$HOME"/.lfe/lib) ALL_LIBS="$LFE_ROOTDIR":"$ERL_LIBS":"$PROJ_LIBS""$R3_PROJ_LIBS""$LFE_HOME_LIBS" + ERL_LIBS="$ALL_LIBS" exec "$emulator" +B -boot start_clean $shebangs "-noshell" "-run" "lfescript" "start" "$@"
View file
_service:tar_scm:lfe-1.3.tar.gz/c_src/lfeexec.c -> _service:tar_scm:lfe-2.1.1.tar.gz/c_src/lfeexec.c
Changed
@@ -1,5 +1,5 @@ /* - * Copyright (c) 2008-2014 Robert Virding + * Copyright (c) 2008-2020 Robert Virding * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License.
View file
_service:tar_scm:lfe-1.3.tar.gz/dev/record-test.lfe -> _service:tar_scm:lfe-2.1.1.tar.gz/dev/record-test.lfe
Changed
@@ -21,6 +21,9 @@ (defun d (p c) (tuple (point-x p) (circle-radius c))) +(defun d2 + (p (when (=:= (point-y p) 99)) 'ok)) + (defun e (p c) (tuple (case p ((match-point x x) x)
View file
_service:tar_scm:lfe-1.3.tar.gz/dev/record_test.erl -> _service:tar_scm:lfe-2.1.1.tar.gz/dev/record_test.erl
Changed
@@ -21,6 +21,9 @@ d(P, C) -> {P#point.x,C#circle.radius}. +d2(PP) when (element(2, PP))#point.y =:= 99 -> + (element(2, PP))#point.x. + e(P, C) -> {case P of #point{x=X} -> X;
View file
_service:tar_scm:lfe-1.3.tar.gz/doc/lfe.txt -> _service:tar_scm:lfe-2.1.1.tar.gz/doc/lfe.txt
Changed
@@ -37,14 +37,6 @@ Clear the REPL output. - (doc | describe Mod) - - (doc | describe Mod:Mac) - - (doc | describe Mod:Fun/Arity) - - Print out documentation of a module/macro/function. - (ec File Options) Compile and load an Erlang file. @@ -66,11 +58,23 @@ Print usage info. + (h Mod) + + (h Mod Mac) + + (h Mod Fun Arity) + + Print out help information of a module/macro/function. + (i (list Pid ...)) Print information about a list of pids. If no list is given then print information about currently running processes in the system. + (i x y z) + + Print information about the about #Pid<x.y.z> + (l Module ...) Load modules. @@ -117,7 +121,7 @@ (reset-environment) Resets the environment to its initial state. This will clear all vari‐ - ables, functions an macros that have been set. + ables, functions and macros that have been set. (run File) @@ -165,7 +169,7 @@ *, **, *** - The values of the previous 3 expressions. + The values of the previous three expressions. - @@ -199,9 +203,11 @@ Flags that LFE recognizes include the following: + · -nobanner - starts LFE without showing the banner + · -h or --help - provides command line usage help - · -e or -eval - evaluates a given sexpr + · -e or -eval - evaluates a given sexpr in a string · -prompt - users may supply a value here to override the default lfe> prompt; note that -prompt classic will set the prompt to the original @@ -212,14 +218,24 @@ taining the string ~node (which will be substituted with the actual name of the node). + There can be multiple string expressions to be evaluated; each one must + be prefixed with an -e or -eval. String expressions are run in the LFE + repl so shell commands and functions are allowed. They are all run in + the same invocation of the repl so: + + $ lfe -e "(set aaa 42)" -e "(set bbb 84)" -e "(pp (tuple aaa bbb))" + #(42 84) + + If there are string expressions then the LFE repl will not be run. + RUNNING LFE SHELL SCRIPTS - The LFE shell can also be directly called to run LFE shell scripts + The LFE shell can also be directly called to run LFE shell scripts with: lfe flags file args - This will start the shell, run a script with LFE shell commands and - then terminate the shell. The following built-in variables are also + This will start the shell, run a script with LFE shell commands and + then terminate the shell. The following built-in variables are also bound: script-name @@ -231,6 +247,14 @@ A list of the arguments to the script as strings. If no arguments have been given then this will be an empty list. + Note that if there are any string expressions to be evaluated then + these must come before the name of the script file and its arguments. + These expressions will be evaluated before the script and the script + will use the environment from the string expressions. + + It is possible to run both string expressions and an LFE shell script + and they are then run in the same LFE repl. + SEE ALSO lfescript(1), lfe_guide(7) lfe_doc(3) @@ -239,4 +263,4 @@ - 2008-2016 lfe(1) + 2008-2020 lfe(1)
View file
_service:tar_scm:lfe-1.3.tar.gz/doc/lfe_bits.txt -> _service:tar_scm:lfe-2.1.1.tar.gz/doc/lfe_bits.txt
Changed
@@ -16,7 +16,7 @@ {error,Error}. Parse a bitspec and return the data. Unmentioned fields get the value - 'default'. + `default'. get_bitspecs(Specs) -> @@ -24,7 +24,7 @@ {error,Error}. Parse a bitspec, apply defaults and return the data. Unmentioned - fields get the value 'default'. + fields get the value `default'. ERROR INFORMATION The following error values are returned:
View file
_service:tar_scm:lfe-1.3.tar.gz/doc/lfe_cl.txt -> _service:tar_scm:lfe-2.1.1.tar.gz/doc/lfe_cl.txt
Changed
@@ -7,7 +7,7 @@ SYNOPSIS This module provides a set of Common Lisp functions and macros for use - in LFE. The definitions closely follow the CL definitions and won't be + in LFE. The definitions closely follow the CL definitions and won’t be documented here. DATA TYPES @@ -50,10 +50,10 @@ remprop symbol pname - Atoms (symbols) in LFE don't have property lists associated with them. - However, here we have experimented with having a global ETS table - lfe-symbol-plist which associates an atom with a property list. This - is very unLFEy, but quite fun. + Atoms (symbols) in LFE don’t have property lists associated with them. + However, here we have experimented with having a global ETS table lfe- + symbol-plist which associates an atom with a property list. This is + very unLFEy, but quite fun. Property list functions getf plist pname @@ -87,11 +87,11 @@ reduce function sequence - reduce function sequence 'initial-value x + reduce function sequence ’initial-value x - reduce function sequence 'from-end 'true + reduce function sequence ’from-end ’true - reduce function sequence 'initial-value x 'from-end 'true + reduce function sequence ’initial-value x ’from-end ’true Modifying sequences remove item sequence
View file
_service:tar_scm:lfe-1.3.tar.gz/doc/lfe_clj.txt -> _service:tar_scm:lfe-2.1.1.tar.gz/doc/lfe_clj.txt
Changed
@@ -6,7 +6,7 @@ clj - LFE Clojure interface library. SYNOPSIS - This module provides Clojure-inpired functions and macros for use in + This module provides Clojure-inspired functions and macros for use in LFE. EXPORTS @@ -36,7 +36,7 @@ Equivalent to lambda. Threading Macros - Note: The original versions were copied from Tim Dysinger's lfesl repo + Note: The original versions were copied from Tim Dysinger’s lfesl repo here: https://github.com/lfex/lfesl/blob/master/include/thread.lfe @@ -132,7 +132,7 @@ Given an expression and a set of test/sexp pairs, thread x (via ->) through each sexp for which the corresponding test expression is - truthy, i.e. neither 'false nor 'undefined. Note that, unlike cond + truthy, i.e. neither 'false nor 'undefined. Note that, unlike cond branching, cond-> threading does not short circuit after the first truthy test expression. @@ -140,7 +140,7 @@ Given an expression and a set of test/sexp pairs, thread x (via ->>) through each sexp for which the corresponding test expression is - truthy, i.e. neither 'false nor 'undefined. Note that, unlike cond + truthy, i.e. neither 'false nor 'undefined. Note that, unlike cond branching, cond->> threading does not short circuit after the first truthy test expression. @@ -176,7 +176,7 @@ test-expr >> result-fn - where result-fn is a unary function, if (pred test-expr expr) returns + where result-fn is a unary function, if (pred test-expr expr) returns anything other than 'undefined or 'false, the clause is a match. If a binary clause matches, return result-expr. If a ternary clause @@ -196,7 +196,7 @@ (iff test . body) - Like Clojure's when. If test evaluates to anything other than 'false + Like Clojure’s when. If test evaluates to anything other than 'false or 'undefined, evaluate body in an implicit progn. (when-not test . body) @@ -336,8 +336,8 @@ of their string representations. N.B. Because Erlang characters are represented as integers, this will - not work for chars, e.g. #\a, which will be presented in the return - value as its integer value, i.e. "97". + not work for chars, e.g. #\a, which will be presented in the return + value as its integer value, i.e. "97". > (clj:str #\a "bc") "97bc" @@ -539,7 +539,7 @@ Return a nullary function that returns a cons cell with start as the head and a nullary function, (next func (funcall func start step) step) as the tail. The result can be treated as a (possibly infinite) lazy - list, which only computes subseqeuent values as needed. + list, which only computes subsequent values as needed. (lazy-seq seq) @@ -570,18 +570,18 @@ (drop n lst) - (drop 'all lst) + (drop ’all lst) Return a list of all but the first n elements in lst. If n is the atom all, return the empty list. (take n lst) - (take 'all lst) + (take ’all lst) Given a (possibly lazy) list lst, return a list of the first n elements of lst, or all elements if there are fewer than n. If n is the atom - all and lst is a "normal" list, return lst. + all and lst is a “normal” list, return lst. (split-at n lst) @@ -599,7 +599,7 @@ Return a list of lists of n items each, at offsets step apart. Use the elements of pad as necessary to complete the last partition up to n el‐ - ements. In case there are not enough padding elements, return a pari‐ + ements. In case there are not enough padding elements, return a parti‐ tion with less than n items. (partition-all n lst) @@ -654,8 +654,8 @@ (constantly x) - Return a unary function that returns x. N.B. This is like Haskell's - const rather than Clojure's constantly. + Return a unary function that returns x. N.B. This is like Haskell’s + const rather than Clojure’s constantly. (inc x)
View file
_service:tar_scm:lfe-1.3.tar.gz/doc/lfe_comp.txt -> _service:tar_scm:lfe-2.1.1.tar.gz/doc/lfe_comp.txt
Changed
@@ -48,6 +48,10 @@ LFE code in the files .lint. No object files are produced. Mainly useful for debugging and interest. + · to_erlang, to-erlang - Print a listing of the Erlang AST in the file + .erl. No object files are produced. Mainly useful for debugging and + interest. + · to_core0, to-core0, to_core, to-core - Print a listing of the Core Erlang code before/after being optimised in the files .core. No ob‐ ject files are produced. Mainly useful for debugging and interest. @@ -111,8 +115,8 @@ Compile the forms as an LFE module returning a binary. This function takes the same options as lfe_comp:file/1/2. When generating Errors - and Warnings the "line number" is the index of the form in which the - error occured. + and Warnings the “line number” is the index of the form in which the + error occurred. format_error(Error) -> Chars
View file
_service:tar_scm:lfe-2.1.1.tar.gz/doc/lfe_docs.txt
Added
@@ -0,0 +1,34 @@ +lfe_docs(3) lfe_docs(3) + + + +NAME + lfe_docs - Lisp Flavoured Erlang (LFE) documentation handling. + +SYNOPSIS + This module provides functions to parse docstrings in LFE module + sources in EEP48 format. + +EXPORTS + make_chunk(Mod, CompilerInfo) -> {ok,DocsChunk} + + Parse a module’s docstrings and return a documentation chunk. + + make_docs_info(Mod, CompilerInfo) -> {ok,DocsInfo} + + Parse a module’s docstrings and return the documentation info. + + get_module_docs(Module | Binary) -> {ok,DocsInfo} | {error,Error} + + Extract the documentation from a module documentation chunk and return + it in the documentation format of the current Erlang version. + +SEE ALSO + lfe_comp(3), lfe_macro(3) + +AUTHORS + Robert Virding. + + + + 2016 lfe_docs(3)
View file
_service:tar_scm:lfe-1.3.tar.gz/doc/lfe_guide.txt -> _service:tar_scm:lfe-2.1.1.tar.gz/doc/lfe_guide.txt
Changed
@@ -3,10 +3,10 @@ NAME - lfe_guide - Lisp Flavoured Erlang User Guide + lfe_guide ‐ Lisp Flavoured Erlang User Guide -SYNPOSIS - Note: {{ ... }} is use to denote optional syntax. +SYNOPSIS + Note: {{ ... }} is used to denote optional syntax. LITERALS AND SPECIAL SYNTACTIC RULES Integers @@ -14,27 +14,27 @@ · Regular decimal notation: - 1234 -123 0 + 1234 ‐123 0 · Binary notation: - #b0 #b10101 #b-1100 + #b0 #b10101 #b‐1100 · Binary notation (alternative form): - #*0 #b*10101 #*-1100 + #*0 #*10101 #*‐1100 · Octal notation: - #o377 #o-111 + #o377 #o‐111 · Explicitly decimal notation: - #d1234 #d-123 #d0 + #d1234 #d‐123 #d0 · Hexadecimal notation: - #xc0ffe 0x-01 + #xc0ffe #x‐01 · Notation with explicit base (up to 36): @@ -50,58 +50,58 @@ #\x1f42d; In all these forms, the case of the indicating letter is not signifi‐ - cant, i.e. #b1010 and #B1010 are identical as are #16rf00 and #16Rf00. + cant, i.e. #b1010 and #B1010 are identical as are #16rf00 and #16Rf00. - Similarly, the case is not significant for digits beyond 9 (i.e. 'a', - 'b', 'c', ... for number bases larger than 10), e.g. #xabcd is the - same as #xABCD and can even be mixed in the same number, e.g. #36rHel‐ - loWorld is valid and the same number as #36Rhelloworld and #36rHEL‐ + Similarly, the case is not significant for digits beyond 9 (i.e. ‘a’, + ‘b’, ‘c’, ... for number bases larger than 10), e.g. #xabcd is the + same as #xABCD and can even be mixed in the same number, e.g. #36rHel‐ + loWorld is valid and the same number as #36Rhelloworld and #36rHEL‐ LOWORLD. The character notation using hexadecimal code representation (#\x....;) - is basically the same thing as the regular hexadecimal notation #x... - except that it conveys to the reader that a character is intended and - that it does a sanity check on the value (e.g. negative numbers and + is basically the same thing as the regular hexadecimal notation #x... + except that it conveys to the reader that a character is intended and + that it does a sanity check on the value (e.g. negative numbers and value outside the Unicode range are not permitted). Floating point numbers - There is only one type of floating point numbers and the literals are - written in the usual way, e.g. these are all valid floating point num‐ + There is only one type of floating point numbers and the literals are + written in the usual way, e.g. these are all valid floating point num‐ bers: - 1.0 +1.0 -1.0 1.0e10 1.111e-10 + 1.0 +1.0 ‐1.0 1.0e10 1.111e‐10 - The one thing to watch out for is that you cannot omit the the part be‐ - fore or after the decimal point if it is zero. E.g. the following are - not valid forms: 100. or .125. + The one thing to watch out for is that you cannot omit the part before + or after the decimal point if it is zero. E.g. the following are not + valid forms: 100. or .125. Strings There are two forms of strings: list strings and binary strings. List Strings - List strings are just lists of integers (where the values have to be + List strings are just lists of integers (where the values have to be from a certain set of numbers that are considered valid characters) but - they have their own syntax for literals (which will also be used for - integer lists as an output representation if the list contents looks - like it is meant to be a string): "any text between double quotes where - " and other special characters like \n can be escaped". - - As a special case you can also write out the character number in the - form \xHHH; (where "HHH" is an integer in hexadecimal notation), e.g. - "\x61;\x62;\x63;" is a complicated way of writing "abc". This can be - convenient when writing Unicode letters not easily typeable or viewable - with regular fonts. E.g. "Cat: \\x1f639;" might be easier to type - (and view on output devices without a Unicode font) then typing the ac‐ - tual unicode letter. + they have their own syntax for literals (which will also be used for + integer lists as an output representation if the list contents looks + like it is meant to be a string): “any text between double quotes where + " and other special characters like \n can be escaped”. + + As a special case you can also write out the character number in the + form \xHHH; (where “HHH” is an integer in hexadecimal notation), + e.g. "\x61;\x62;\x63;" is a complicated way of writing "abc". This can + be convenient when writing Unicode letters not easily typeable or view‐ + able with regular fonts. E.g. "Cat: \\x1f639;" might be easier to + type (and view on output devices without a Unicode font) then typing + the actual Unicode letter. Binary Strings Binary strings are just like list strings but they are represented dif‐ - ferently in the virtual machine. The simple syntax is #"...", e.g. - #"This is a binary string \n with some \"escaped\" and quot‐ - ed (\\x1f639;) characters" + ferently in the virtual machine. The simple syntax is #"...", e.g. + #"This is a binary string \n with some \"escaped\" and quoted + (\\x1f639;) characters" You can also use the general format for creating binaries (#B(...), de‐ - scribed below), e.g. #B("a"), #"a", and #B(97) are all the same binary + scribed below), e.g. #B("a"), #"a", and #B(97) are all the same binary string. Character Escaping @@ -109,7 +109,7 @@ escaped name: | Escaped name | Character | - |--------------+-----------------| + |‐‐‐‐‐‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐| | \b | Backspace | | \t | Tab | | \n | Newline | @@ -120,21 +120,21 @@ | \s | Space | | \d | Delete | - Alternatively you can also use the hexadecimal character encoding, e.g. - "a\nb" and "a\x0a;b" are the same string. + Alternatively you can also use the hexadecimal character encoding, + e.g. "a\nb" and "a\x0a;b" are the same string. Binaries We have already seen binary strings, but the #B(...) syntax can be used - to create binaries with any contents. Unless the contents is a simple + to create binaries with any contents. Unless the contents is a simple integer you need to annotate it with a type and/or size. Example invocations are that show the various annotations: > #B(42 (42 (size 16)) (42 (size 32))) #B(42 0 42 0 0 0 42) - > #B(-42 111 (-42 (size 16)) 111 (-42 (size 32))) - #B(-42 111 (-42 (size 16)) 111 (-42 (size 32))) - > #B((42 (size 32) big-endian) (42 (size 32) little-endian)) + > #B(‐42 111 (‐42 (size 16)) 111 (‐42 (size 32))) + #B(‐42 111 (‐42 (size 16)) 111 (‐42 (size 32))) + > #B((42 (size 32) big‐endian) (42 (size 32) little‐endian)) #B(0 0 0 42 42 0 0 0) > #B((1.23 float) (1.23 (size 32) float) (1.23 (size 64) float)) #B(63 243 174 20 122 225 71 174 63 157 112 164 63 243 174 20 @@ -142,13 +142,13 @@ > #B((#"a" binary) (#"b" binary)) #"ab" - Learn more about "segments" of binary data e.g. in "Learn You Some Er‐ - lang (http://learnyousomeerlang.com/starting-out-for-real#bit-syntax)" - <http://learnyousomeerlang.com/starting-out-for-real#bit-syntax>. + Learn more about “segments” of binary data e.g. in “Learn You Some Er‐ + lang (http://learnyousomeerlang.com/starting‐out‐for‐real#bit‐syntax)” + <http://learnyousomeerlang.com/starting‐out‐for‐real#bit‐syntax>. Lists - Lists are formed either as ( ... ) or ... where the optional ele‐ - ments of the list are separated by some form or whitespace. For exam‐ + Lists are formed either as ( ... ) or ... where the optional ele‐ + ments of the list are separated by some form or whitespace. For exam‐ ple: () @@ -163,33 +163,33 @@ so valid. Maps - Maps are written as #M(key1 value1 key2 value2 ...) The empty map is + Maps are written as #M(key1 value1 key2 value2 ...) The empty map is
View file
_service:tar_scm:lfe-1.3.tar.gz/doc/lfe_io.txt -> _service:tar_scm:lfe-2.1.1.tar.gz/doc/lfe_io.txt
Changed
@@ -25,13 +25,13 @@ compiler to give better error information. EXPORTS - read(IoDevice, Prompt) -> {ok,Sexpr} | {error,ErrorInfo} + read(IoDevice, Prompt) -> {ok,Sexpr} | {error,ErrorInfo} | eof Read an s-expr from the standard input (IoDevice) with a prompt (Prompt). Note that this is not line-oriented in that it stops as soon as it has consumed enough characters. - read_line(IoDevice, Prompt) -> {ok,Sexpr} | {error,ErrorInfo} + read_line(IoDevice, Prompt) -> {ok,Sexpr} | {error,ErrorInfo} | eof Read an s-expr from the standard input (IoDevice) with a prompt (Prompt). Note that this is line-oriented in that it reads whole lines @@ -39,7 +39,8 @@ read_string(String) -> {ok,Sexpr} | {error,ErrorInfo} - Read an s-expr from String. + Read an s-expr from String. Note that this only reads from String dis‐ + carding left-over characters at the end of the string. print(IoDevice, Sexpr) -> ok @@ -49,6 +50,10 @@ Return the list of characters which represent the s-expr Sexpr. + prettyprint(IoDevice, Sexpr) -> ok + + Pretty print the s-expr Sexpr to the standard output (IoDevice). + prettyprint1(Sexpr) -> DeepCharList prettyprint1(Sexpr, Depth) -> DeepCharList @@ -57,8 +62,9 @@ prettyprint1(Sexpr, Depth, Indentation, LineLength) -> DeepCharList - Return the lost of characters which represents the prettyprinted s-expr - Sexpr. Assume we start at indentation Indentation or 0. + Return the list of characters which represents the prettyprinted s-expr + Sexpr. Default values for Depth is 30, Indentation is 0 and LineLength + is 80. format(IoDevice, Format, Args) -> ok @@ -133,4 +139,4 @@ - 2008-2016 lfe_io(3) + 2008-2019 lfe_io(3)
View file
_service:tar_scm:lfe-1.3.tar.gz/doc/lfe_macro.txt -> _service:tar_scm:lfe-2.1.1.tar.gz/doc/lfe_macro.txt
Changed
@@ -25,22 +25,26 @@ This is an macro and evaluation environment as created by lfe_lib:new_env(). -EXPORTS - expand_forms(FileSexpr, Env) -> ExpRet + mac_state() - where + This is the internal state used by the macro expander. - FileSexpr = filesexpr() - Env = env() - ExpRet = {yes,FileSexpr,Env,Warnings} | {error,Errors,Warnings} +EXPORTS + expand_expr(Sexpr, Env) -> {yes,Exp} | no. - macro_forms(FileSexpr, Env) -> {FileSexpr,Env}. + expand_expr_1(Sexpr, Env) -> {yes,Exp} | no. where - FileSexpr = filesexpr() + Sexpr = Exp = sexpr() Env = env() + Test if the top s-expression here is a macro call, if so expand it and + return {yes,Expansion}, if not then return no. expand_expr/2 will ex‐ + pand the top s-expression as much as possible while expand_expr_1/2 + will only try it once. These functions use the macro definitions in + the environment and the standard pre-defined macros. + expand_expr_all(Sexpr, Env) -> Sexpr. where @@ -52,20 +56,49 @@ the default macros. Note that any eventual new macro definitions will be lost. - expand_expr(Sexpr, Env) -> {yes,Exp} | no. + expand_form_init(Deep, Keep) -> MacState - expand_expr_1(Sexpr, Env) -> {yes,Exp} | no. + where + + Deep = boolean() + Keep = boolean() + MacState = mac_state() + + Create an internal macro state. Deep determines whether the form is to + be expanded internally at depth and Keep whether macro definition forms + are to be kept. + + expand_fileforms(FileForm, Env, Deep, Keep) -> ExpRet + + expand_fileforms(FileForm, Env, MacState) -> ExpRet where - Sexpr = Exp = sexpr() - Env = env() + FileForm = filesexpr() + Env = env() + Deep = boolean() + Keep = boolean() + MacState = mac_state() + ExpRet = {yes,FileSexpr,Env,Warnings} | + {error,Errors,Warnings} - Test if the top s-expression here is a macro call, if so expand it and - return {yes,Expansion}, if not then return no. expand_expr/2 will ex‐ - pand the top s-expression as much as possible while expand_expr_1/2 - will only try it once. These functions use the macro definitions in - the environment and the standard pre-defined macros. + expand a sequence of file forms. + + expand_form(Form, Line, Env, MacState) -> RetState + + expand_fileform(FileForm, Env, MacState) -> RetState + + where + + Form = sexpr() + FileForm = filesexpr() + Line = integer() + Env = env() + MacState = mac_state() + RetState = {ok,Form,Env,Macstate} | + {error,Errors,Warnings,MacState} + + Expand a file form using the environment and macro state. SEE ALSO lfe_comp(3), lfe_gen(3) @@ -75,4 +108,4 @@ - 2008-2016 lfe_macro(3) + 2008-2020 lfe_macro(3)
View file
_service:tar_scm:lfe-1.3.tar.gz/doc/lfe_types.txt -> _service:tar_scm:lfe-2.1.1.tar.gz/doc/lfe_types.txt
Changed
@@ -24,9 +24,11 @@ (lambda () <type>) fun(() -> <type>) (lambda (<tlist>) <type>) fun((<tlist>) -> <type>) (map) map() - (map <pairlist>) #{<pairlist>} + #M() #{} + #M(<key> <value> ...) #{<pairlist>} (tuple) tuple() - (tuple <tlist>) {<tlist>} + #() {} + #(<tlist>) {<tlist>} (UNION <tlist>) <type> | <type> Apart from the predefined types in the Erlang type system we also have @@ -34,6 +36,10 @@ lambda and range. The usage of bitstring, tuple and map have also been extended. + Note that the type #M() is the empty map and the type #() is the empty + tuple. We can still use the older (map <key valuelist>) and (tuple + <tlist>) formats when declaring types for maps and tuples. + The general form of bitstrings is (bitstring m n) which denotes a bit‐ string which starts with m bits and continues with segments of n bits. (binary) is a short form for a sequence of bytes while (bitstring) is a @@ -57,7 +63,7 @@ (deftype bar (tuple 'bar (integer) (list))) Type Information in Record Declarations - (defrecord rec (field1 default1 type1) (field2 default2) field3) + (defrecord rec (field1 default1 type1) (field2 default2) (field3)) Fields with type annotations MUST give a default value and fields with‐ out type annotations get the default type (any). @@ -97,16 +103,27 @@ (defspec (remove-if 2) (pred (list) (list) (pred (lambda ((any)) (boolean))))) - Note that a constraint variable doesn't need to start with an up‐ - per-case like an Erlang variable, though in some case it may be easier - to read. + Note that a constraint variable doesn’t need to start with an upper- + case like an Erlang variable, though in some case it may be easier to + read. Note we are using the alternate list form with instead of parenthe‐ ses to make it easier to see the function arguments. +Types and function specifications in the module definition + Types can also be defined in the module declaration, for example: + + (defmodule this-module + ... + (type ((foo-type) (tuple 'foo (integer) (list))) + ((bar-type) (tuple 'bar (integer) (list)))) + (spec ((foo 1) ((integer) (foo-type))) + ((id 1) (x x ((x (tuple)))))) + ...) + AUTHORS Robert Virding. - 2016 lfe_types(7) + 2021 lfe_types(7)
View file
_service:tar_scm:lfe-1.3.tar.gz/doc/lfescript.txt -> _service:tar_scm:lfe-2.1.1.tar.gz/doc/lfescript.txt
Changed
@@ -64,11 +64,11 @@ In the example the second line is an optional directive to Emacs which causes it to enter LFE mode when editing the script file. - The rest of the file contains LFE source code. It must always the - function main/1. When the script is run this function will be called - with a list of strings representing the arguments with which the script - was called. It is possible to define, include and use macros in the - source code. + The rest of the file contains LFE source code. It must always contain + the function main/1. When the script is run this function will be + called with a list of strings representing the arguments with which the + script was called. It is possible to define, include and use macros in + the source code. The source code is checked and warnings and errors will be printed. If there are errors the script will not run and it will terminate with ex‐ @@ -89,7 +89,7 @@ ENVIRONMENT VARIABLES LFESCRIPT_EMULATOR - The command used to start the emulator. Default is 'erl'. This can be + The command used to start the emulator. Default is `erl'. This can be useful for passing arguments into the emulator, for example LFESCRIPT_EMULATOR="erl -pa sune"
View file
_service:tar_scm:lfe-1.3.tar.gz/doc/man/lfe.1 -> _service:tar_scm:lfe-2.1.1.tar.gz/doc/man/lfe.1
Changed
@@ -1,151 +1,155 @@ -.\" Automatically generated by Pandoc 1.19.2.1 +.\" Automatically generated by Pandoc 2.11.2 .\" -.TH "lfe" "1" "2008\-2016" "" "" +.TH "lfe" "1" "2008-2020" "" "" .hy .SH NAME .PP -lfe \- Lisp Flavoured Erlang (LFE) shell +lfe - Lisp Flavoured Erlang (LFE) shell .SH SYNOPSIS .PP -\fClfe\f is a simple LFE repl (read\-eval\-print loop) in which you +\fClfe\fR is a simple LFE repl (read-eval-print loop) in which you can enter sexprs which then are evaluated and the value printed. You can also define local functions and macros as well as set variables. It can read commands either from the standard input or from a file. .PP -The LFE repl is implemented in the module \fClfe_shell\f. -.SH BUILT\-IN SHELL FUNCTIONS +The LFE repl is implemented in the module \fClfe_shell\fR. +.SH BUILT-IN SHELL FUNCTIONS .PP These are defined as normal functions and macros and can be called from anywhere in the shell. They can even be redefined. -They can also be explicitly called (: lfe_shell ...). +They can also be explicitly called (: lfe_shell \&...). .PP -\fB(c File Options)\f +\fB(c File Options)\fR .PP Compile and load an LFE file. -Assumes default extension \fC\&.lfe\f. +Assumes default extension \fC.lfe\fR. .PP -\fB(: c Command Arg ...)\f +\fB(: c Command Arg \&...)\fR .PP -\fB(c:Command Arg ...)\f +\fB(c:Command Arg \&...)\fR .PP All the commands in the standard Erlang shell can be reached in this way. .PP -\fB(cd Dir)\f +\fB(cd Dir)\fR .PP Change the working directory. .PP -\fB(clear)\f +\fB(clear)\fR .PP Clear the REPL output. .PP -\fB(doc | describe Mod)\f -.PP -\fB(doc | describe Mod:Mac)\f -.PP -\fB(doc | describe Mod:Fun/Arity)\f -.PP -Print out documentation of a module/macro/function. -.PP -\fB(ec File Options)\f +\fB(ec File Options)\fR .PP Compile and load an Erlang file. .PP -\fB(ep Expr Depth)\f +\fB(ep Expr Depth)\fR .PP -\fB(epp Expr Depth)\f +\fB(epp Expr Depth)\fR .PP Print/prettyprint a value in Erlang form to either the specified depth or if no value is given the full depth. .PP -\fB(flush)\f +\fB(flush)\fR .PP Flush any messages sent to the shell. .PP -\fB(h)\f +\fB(h)\fR .PP -\fB(help)\f +\fB(help)\fR .PP Print usage info. .PP -\fB(i (list Pid ...))\f +\fB(h Mod)\fR +.PP +\fB(h Mod Mac)\fR +.PP +\fB(h Mod Fun Arity)\fR +.PP +Print out help information of a module/macro/function. +.PP +\fB(i (list Pid \&...))\fR .PP Print information about a list of pids. If no list is given then print information about currently running processes in the system. .PP -\fB(l Module ...)\f +\fB(i x y z)\fR +.PP +Print information about the about #Pid<x.y.z> +.PP +\fB(l Module \&...)\fR .PP Load modules. .PP -\fB(ls)\f +\fB(ls)\fR .PP -\fB(ls dir)\f +\fB(ls dir)\fR .PP List files in a directory. If no directory is given then list files in the current directory. .PP -\fB(m Module ...)\f +\fB(m Module \&...)\fR .PP Print out module information. If no modules are given then print information about all modules. .PP -\fB(p Expr Depth)\f +\fB(p Expr Depth)\fR .PP -\fB(pp Expr Depth)\f +\fB(pp Expr Depth)\fR .PP Print/prettyprint a value to either the specified depth or if no value is given the full depth. .PP -\fB(pid x y z)\f +\fB(pid x y z)\fR .PP Create a pid from x, y, z. .PP -\fB(pwd)\f +\fB(pwd)\fR .PP Print the current working directory. .PP -\fB(q)\f +\fB(q)\fR .PP -Quit \- shorthand for \fCinit:stop/0\f. +Quit - shorthand for \fCinit:stop/0\fR. .PP -\fB(regs)\f +\fB(regs)\fR .PP Print information about the registered processes in the system. -.SH BUILT\-IN SHELL COMMANDS +.SH BUILT-IN SHELL COMMANDS .PP -These are special forms which are only recognised at the top\-level in +These are special forms which are only recognised at the top-level in shell input. The cannot be redefined. .PP -\fB(reset\-environment)\f +\fB(reset-environment)\fR .PP Resets the environment to its initial state. -This will clear all variables, functions an macros that have been set. +This will clear all variables, functions and macros that have been set. .PP -\fB(run File)\f +\fB(run File)\fR .PP Execute all the shell commands in File. All defined variables, functions and macros will be saved in the environment if there are no errors. .PP -\fB(set Pattern Expr)\f +\fB(set Pattern Expr)\fR .PP -\fB(set Pattern (when Guard) Expr)\f +\fB(set Pattern (when Guard) Expr)\fR .PP Evaluate Expr and match the result with Pattern binding variables in it. These variables can then be used in the shell and also rebound in another set. .PP -\fB(slurp File)\f +\fB(slurp File)\fR .PP Slurp in a source LFE file and makes all functions and macros defined in the file available in the shell. Only one file can be slurped at a time and slurping a new file basically does an unslurp first. .PP -\fB(unslurp)\f
View file
_service:tar_scm:lfe-1.3.tar.gz/doc/man/lfe_bits.3 -> _service:tar_scm:lfe-2.1.1.tar.gz/doc/man/lfe_bits.3
Changed
@@ -1,10 +1,10 @@ -.\" Automatically generated by Pandoc 1.19.2.1 +.\" Automatically generated by Pandoc 2.11.2 .\" -.TH "lfe_bits" "3" "2011\-2016" "" "" +.TH "lfe_bits" "3" "2011-2016" "" "" .hy .SH NAME .PP -lfe_bits \- Lisp Flavoured Erlang (LFE) common binary functions +lfe_bits - Lisp Flavoured Erlang (LFE) common binary functions .SH SYNOPSIS .PP This module contains a collection of library functions for for handling @@ -12,35 +12,35 @@ They are generally not called by the user. .SH EXPORTS .PP -\fBparse_bitspecs(Specs) \->\f +\fBparse_bitspecs(Specs) ->\fR .IP .nf \fC -\ \ {ok,Size,{Type,Unit,Sign,Endian}}\ | -\ \ {error,Error}. -\f + {ok,Size,{Type,Unit,Sign,Endian}} | + {error,Error}. +\fR .fi .PP Parse a bitspec and return the data. -Unmentioned fields get the value \aqdefault\aq. +Unmentioned fields get the value `default'. .PP -\fBget_bitspecs(Specs) \->\f +\fBget_bitspecs(Specs) ->\fR .IP .nf \fC -\ \ {ok,Size,{Type,Unit,Sign,Endian}}\ | -\ \ {error,Error}. -\f + {ok,Size,{Type,Unit,Sign,Endian}} | + {error,Error}. +\fR .fi .PP Parse a bitspec, apply defaults and return the data. -Unmentioned fields get the value \aqdefault\aq. +Unmentioned fields get the value `default'. .SH ERROR INFORMATION .PP The following error values are returned: .PP -\fB{undefined_bittype,Type}\f +\fB{undefined_bittype,Type}\fR .PP -\fBbittype_unit\f +\fBbittype_unit\fR .SH AUTHORS Robert Virding.
View file
_service:tar_scm:lfe-1.3.tar.gz/doc/man/lfe_cl.3 -> _service:tar_scm:lfe-2.1.1.tar.gz/doc/man/lfe_cl.3
Changed
@@ -1,260 +1,260 @@ -.\" Automatically generated by Pandoc 1.19.2.1 +.\" Automatically generated by Pandoc 2.11.2 .\" .TH "lfe_cl" "3" "2017" "" "" .hy .SH NAME .PP -lfe_cl \- LFE Common Lisp interface library +lfe_cl - LFE Common Lisp interface library .SH SYNOPSIS .PP This module provides a set of Common Lisp functions and macros for use in LFE. -The definitions closely follow the CL definitions and won\aqt be +The definitions closely follow the CL definitions and won\cqt be documented here. .SH DATA TYPES .PP -The boolean values used here are the standard LFE \fCtrue\f and -\fCfalse\f and \fBNOT\f the Common Lisp values. +The boolean values used here are the standard LFE \fCtrue\fR and +\fCfalse\fR and \fBNOT\fR the Common Lisp values. .SH EXPORTS .SS Boolean conversion functions .PP -\fBmake\-lfe\-bool cl\-value\f +\fBmake-lfe-bool cl-value\fR .PP -\fBmake\-cl\-bool lfe\-bool\f +\fBmake-cl-bool lfe-bool\fR .SS Control structures .PP -\fB\fCdo\ vars\ (end\-test\ result)\ body\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ macro\f\f +\fB\fCBdo vars (end-test result) body macro\fB\fR .PP -The value of \fCbody\f is bound the variable \fCdo\-state\f -which can be used when updating vars and in the \fCend\-test\f. +The value of \fCbody\fR is bound the variable \fCdo-state\fR +which can be used when updating vars and in the \fCend-test\fR. This is the only way to get a value out of the body. .PP -\fBmapcar function list\f +\fBmapcar function list\fR .PP -\fBmaplist function list\f +\fBmaplist function list\fR .PP -\fBmapc function list\f +\fBmapc function list\fR .PP -\fBmapl function list\f +\fBmapl function list\fR .SS Symbol functions .PP -\fBsymbol\-plist symbol\f +\fBsymbol-plist symbol\fR .PP -\fBsymbol\-name symbol\f +\fBsymbol-name symbol\fR .PP -\fBget symbol pname\f +\fBget symbol pname\fR .PP -\fBget symbol pname default\f +\fBget symbol pname default\fR .PP -\fBgetl symbol pname\-list\f +\fBgetl symbol pname-list\fR .PP -\fBputprop symbol value pname\f +\fBputprop symbol value pname\fR .PP -\fBremprop symbol pname\f +\fBremprop symbol pname\fR .PP -Atoms (symbols) in LFE don\aqt have property lists associated with +Atoms (symbols) in LFE don\cqt have property lists associated with them. However, here we have experimented with having a global ETS table -\fClfe\-symbol\-plist\f which associates an atom with a property +\fClfe-symbol-plist\fR which associates an atom with a property list. This is very unLFEy, but quite fun. .SS Property list functions .PP -\fBgetf plist pname\f +\fBgetf plist pname\fR .PP -\fBgetf plist pname default\f +\fBgetf plist pname default\fR .PP -\fBputf plist value pname\f +\fBputf plist value pname\fR .PP -\fBremf plist pname\f +\fBremf plist pname\fR .PP -\fBget\-properties plist pname\-list\f +\fBget-properties plist pname-list\fR .PP -The function \fCputf/3\f does not exist in Common Lisp but is +The function \fCputf/3\fR does not exist in Common Lisp but is included to complete the operations on property lists. .SS Simple sequence functions .PP -\fBelt index sequence\f +\fBelt index sequence\fR .PP -\fBlength sequence\f +\fBlength sequence\fR .PP -\fBreverse sequence\f +\fBreverse sequence\fR .SS Concatenation, mapping and reducing functions .PP -\fBsome predicate sequence\f +\fBsome predicate sequence\fR .PP -\fBevery predicate sequence\f +\fBevery predicate sequence\fR .PP -\fBnotany predicate sequence\f +\fBnotany predicate sequence\fR .PP -\fBnotevery predicate sequence\f +\fBnotevery predicate sequence\fR .PP -\fBreduce function sequence\f +\fBreduce function sequence\fR .PP -\fBreduce function sequence \aqinitial\-value x\f +\fBreduce function sequence \cqinitial-value x\fR .PP -\fBreduce function sequence \aqfrom\-end \aqtrue\f +\fBreduce function sequence \cqfrom-end \cqtrue\fR .PP -\fBreduce function sequence \aqinitial\-value x \aqfrom\-end -\aqtrue\f +\fBreduce function sequence \cqinitial-value x \cqfrom-end +\cqtrue\fR .SS Modifying sequences .PP -\fBremove item sequence\f +\fBremove item sequence\fR .PP -\fBremove\-if predicate sequence\f +\fBremove-if predicate sequence\fR .PP -\fBremove\-if\-not predicate sequence\f +\fBremove-if-not predicate sequence\fR .PP -\fBremove\-duplicates sequence\f +\fBremove-duplicates sequence\fR .PP -\fBsubstitute new old sequence\f +\fBsubstitute new old sequence\fR .PP -\fBsubstitute\-if predicate sequence\f +\fBsubstitute-if predicate sequence\fR .PP -\fBsubstitute\-if\-not predicate sequence\f +\fBsubstitute-if-not predicate sequence\fR .SS Searching sequences .PP -\fBfind item sequence\f +\fBfind item sequence\fR .PP -\fBfind\-if predicate sequence\f +\fBfind-if predicate sequence\fR .PP -\fBfind\-if\-not predicate sequence\f +\fBfind-if-not predicate sequence\fR .PP -\fBfind\-duplicates sequence\f +\fBfind-duplicates sequence\fR .PP -\fBposition item sequence\f +\fBposition item sequence\fR .PP -\fBposition\-if predicate sequence\f +\fBposition-if predicate sequence\fR .PP -\fBposition\-if\-not predicate sequence\f +\fBposition-if-not predicate sequence\fR .PP -\fBposition\-duplicates sequence\f +\fBposition-duplicates sequence\fR .PP -\fBcount item sequence\f +\fBcount item sequence\fR .PP -\fBcount\-if predicate sequence\f +\fBcount-if predicate sequence\fR .PP -\fBcount\-if\-not predicate sequence\f +\fBcount-if-not predicate sequence\fR .SS Lists .PP -\fBcar list\f
View file
_service:tar_scm:lfe-1.3.tar.gz/doc/man/lfe_clj.3 -> _service:tar_scm:lfe-2.1.1.tar.gz/doc/man/lfe_clj.3
Changed
@@ -1,59 +1,60 @@ -.\" Automatically generated by Pandoc 1.19.2.1 +.\" Automatically generated by Pandoc 2.11.2 .\" -.TH "lfe_clj" "3" "2015\-2016" "" "" +.TH "lfe_clj" "3" "2015-2016" "" "" .hy .SH NAME .PP -clj \- LFE Clojure interface library. +clj - LFE Clojure interface library. .SH SYNOPSIS .PP -This module provides Clojure\-inpired functions and macros for use in +This module provides Clojure-inspired functions and macros for use in LFE. .SH EXPORTS .PP N.B. -Instead of making fully\-qualified calls to the macros exported from -\fIclj\f, you may \fC(include\-lib\ "lfe/include/clj.lfe")\f and -then call them directly, e.g. +Instead of making fully-qualified calls to the macros exported from +\fIclj\fR, you may +\fC(include-lib \dqlfe/include/clj.lfe\dq)\fR and then call them +directly, e.g. .IP .nf \fC -(include\-lib\ "lfe/include/clj.lfe") +(include-lib \dqlfe/include/clj.lfe\dq) -(\->\ 2\ (+\ 2)\ (=:=\ 4))\ ;\ \aqtrue -\f +(-> 2 (+ 2) (=:= 4)) ; \aqtrue +\fR .fi .SS Function Macros .PP -\fB(defn name arg ... {{doc\-string}} ...)\f +\fB(defn name arg \&... {{doc-string}} \&...)\fR .PP -\fB(defn {{doc\-string}} (argpat ... ...))\f +\fB(defn {{doc-string}} (argpat \&... \&...))\fR .PP Define and automatically export a function. .PP -\fB(defn\- name arg ... {{doc\-string}} ...)\f +\fB(defn- name arg \&... {{doc-string}} \&...)\fR .PP -\fB(defn\- {{doc\-string}} (argpat ... ...))\f +\fB(defn- {{doc-string}} (argpat \&... \&...))\fR .PP -Equivalent to \fBdefun\f. +Equivalent to \fBdefun\fR. .PP -\fB(fn (arg ...) ...)\f +\fB(fn (arg \&...) \&...)\fR .PP -Equivalent to \fClambda\f. +Equivalent to \fClambda\fR. .SS Threading Macros .PP -Note: The original versions were copied from Tim Dysinger\aqs lfesl +Note: The original versions were copied from Tim Dysinger\cqs lfesl repo here: .IP .nf \fC https://github.com/lfex/lfesl/blob/master/include/thread.lfe -\f +\fR .fi .PP They have since been modified to be safely exportable. .PP -\fB(\-> ...)\f +\fB(-> \&...)\fR .PP Thread first. .PP @@ -61,52 +62,52 @@ .IP .nf \fC ->\ (set\ o\ \aq(#(a\ 1)\ #(b\ 2)\ #(c\ 3))) -(#(a\ 1)\ #(b\ 2)\ #(c\ 3)) ->\ (clj:\->\ o ->\ \ \ \ \ \ \ \ \ (++\ \aq(#(d\ 4))) ->\ \ \ \ \ \ \ \ \ (++\ \aq(#(e\ 5))) ->\ \ \ \ \ \ \ \ \ (++\ \aq(#(f\ 6)))) -(#(a\ 1)\ #(b\ 2)\ #(c\ 3)\ #(d\ 4)\ #(e\ 5)\ #(f\ 6)) -\f +> (set o \aq(#(a 1) #(b 2) #(c 3))) +(#(a 1) #(b 2) #(c 3)) +> (clj:-> o +> (++ \aq(#(d 4))) +> (++ \aq(#(e 5))) +> (++ \aq(#(f 6)))) +(#(a 1) #(b 2) #(c 3) #(d 4) #(e 5) #(f 6)) +\fR .fi .PP -Note that the use of \fB\->\f in this example results in each -successive value being \fIappended\f to the input list. +Note that the use of \fB->\fR in this example results in each +successive value being \fIappended\fR to the input list. .PP Another example showing how this works: .IP .nf \fC ->\ (lists:sublist ->\ \ \ (lists:reverse ->\ \ \ \ \ (lists:sort ->\ \ \ \ \ \ \ (lists:merge ->\ \ \ \ \ \ \ \ \ (string:tokens ->\ \ \ \ \ \ \ \ \ \ \ (string:to_upper\ "a\ b\ c\ d\ e") ->\ \ \ \ \ \ \ \ \ \ \ "\ ") ->\ \ \ \ \ \ \ \ \ \aq("X"\ "F"\ "L")))) ->\ \ \ 2\ 3) -("L"\ "F"\ "E") -\f +> (lists:sublist +> (lists:reverse +> (lists:sort +> (lists:merge +> (string:tokens +> (string:to_upper \dqa b c d e\dq) +> \dq \dq) +> \aq(\dqX\dq \dqF\dq \dqL\dq)))) +> 2 3) +(\dqL\dq \dqF\dq \dqE\dq) +\fR .fi .PP Can be rewritten as this: .IP .nf \fC ->\ (clj:\->\ "a\ b\ c\ d\ e" ->\ \ \ \ \ \ \ \ \ (string:to_upper) ->\ \ \ \ \ \ \ \ \ (string:tokens\ "\ ") ->\ \ \ \ \ \ \ \ \ (lists:merge\ \aq("X"\ "F"\ "L")) ->\ \ \ \ \ \ \ \ \ (lists:sort) ->\ \ \ \ \ \ \ \ \ (lists:reverse) ->\ \ \ \ \ \ \ \ \ (lists:sublist\ 2\ 3)) -("L"\ "F"\ "E") -\f +> (clj:-> \dqa b c d e\dq +> (string:to_upper) +> (string:tokens \dq \dq) +> (lists:merge \aq(\dqX\dq \dqF\dq \dqL\dq)) +> (lists:sort) +> (lists:reverse) +> (lists:sublist 2 3)) +(\dqL\dq \dqF\dq \dqE\dq) +\fR .fi .PP -\fB(\->> ...)\f +\fB(->> \&...)\fR .PP Thread last. .PP @@ -114,419 +115,421 @@ .IP .nf \fC ->\ (set\ o\ \aq(#(a\ 1)\ #(b\ 2)\ #(c\ 3))) -(#(a\ 1)\ #(b\ 2)\ #(c\ 3)) ->\ (clj:\->>\ o ->\ \ \ \ \ \ \ \ \ \ (++\ \aq(#(d\ 4))) ->\ \ \ \ \ \ \ \ \ \ (++\ \aq(#(e\ 5))) ->\ \ \ \ \ \ \ \ \ \ (++\ \aq(#(f\ 6)))) -(#(f\ 6)\ #(e\ 5)\ #(d\ 4)\ #(a\ 1)\ #(b\ 2)\ #(c\ 3)) -\f +> (set o \aq(#(a 1) #(b 2) #(c 3))) +(#(a 1) #(b 2) #(c 3)) +> (clj:->> o +> (++ \aq(#(d 4))) +> (++ \aq(#(e 5))) +> (++ \aq(#(f 6)))) +(#(f 6) #(e 5) #(d 4) #(a 1) #(b 2) #(c 3)) +\fR .fi .PP -Note that the use of \fB\->>\f in this example results in each -successive value being \fIprepended\f to the input list. +Note that the use of \fB->>\fR in this example results in each +successive value being \fIprepended\fR to the input list. .PP Another example showing how this: .IP .nf \fC ->\ (lists:foldl\ #\aq+/2\ 0 ->\ \ \ (clj:take\ 10 ->\ \ \ \ \ (lists:filter ->\ \ \ \ \ \ \ (clj:comp\ #\aqclj:even?/1\ #\aqclj:round/1)
View file
_service:tar_scm:lfe-1.3.tar.gz/doc/man/lfe_comp.3 -> _service:tar_scm:lfe-2.1.1.tar.gz/doc/man/lfe_comp.3
Changed
@@ -1,10 +1,10 @@ -.\" Automatically generated by Pandoc 1.19.2.1 +.\" Automatically generated by Pandoc 2.11.2 .\" -.TH "lfe_comp" "3" "2008\-2016" "" "" +.TH "lfe_comp" "3" "2008-2016" "" "" .hy .SH NAME .PP -lfe_comp \- Lisp Flavoured Erlang (LFE) compiler +lfe_comp - Lisp Flavoured Erlang (LFE) compiler .SH SYNOPSIS .PP This module provides an interface to the standard LFE compiler. @@ -13,24 +13,24 @@ return binaries which can be loaded directly. .SH EXPORTS .PP -\fBfile(FileName) \-> CompRet\f +\fBfile(FileName) -> CompRet\fR .PP -Is the same as \fCfile(FileName,\ report).\f +Is the same as \fCfile(FileName, report).\fR .PP -\fBfile(FileName, Options) \-> CompRet\f +\fBfile(FileName, Options) -> CompRet\fR .PP where .IP .nf \fC -CompRet\ =\ ModRet\ |\ BinRet\ |\ ErrRet -ModRet\ =\ {ok,ModOk}\ |\ {ok,ModOk,Warnings} -ModOk\ \ =\ {ok,ModuleName}\ |\ {ok,ModuleName,Warnings} -BinRet\ =\ {ok,ModBin}\ |\ {ok,ModBin,Warnings} -ModBin\ =\ {ok,ModuleName,Binary}\ |\ {ok,ModuleName,Binary,Warnings} -ErrRet\ =\ error\ |\ {error,ModErr,Errors,Warnings} -ModErr\ =\ {error,Errors,Warnings} -\f +CompRet = ModRet | BinRet | ErrRet +ModRet = {ok,ModOk} | {ok,ModOk,Warnings} +ModOk = {ok,ModuleName} | {ok,ModuleName,Warnings} +BinRet = {ok,ModBin} | {ok,ModBin,Warnings} +ModBin = {ok,ModuleName,Binary} | {ok,ModuleName,Binary,Warnings} +ErrRet = error | {error,ModErr,Errors,Warnings} +ModErr = {error,Errors,Warnings} +\fR .fi .PP Compile an LFE file, either writing the generated modules to files or @@ -39,102 +39,107 @@ .PP The currently recognised options are: .IP \bu 2 -\fCbinary\f \- Return the binary of the module and do not save it in +\fCbinary\fR - Return the binary of the module and do not save it in a file. .IP \bu 2 -\fCno_docs\f, \fCno\-docs\f \- Do not parse docstrings and write -the \fC"LDoc"\f chunk in the binary of the module. +\fCno_docs\fR, \fCno-docs\fR - Do not parse docstrings and write +the \fC\dqLDoc\dq\fR chunk in the binary of the module. .IP \bu 2 -\fCto_expand\f, \fCto\-expand\f \- Print a listing of the macro +\fCto_expand\fR, \fCto-expand\fR - Print a listing of the macro expanded LFE code in the file .expand. No object file is produced. Mainly useful for debugging and interest. .IP \bu 2 -\fCto_lint\f, \fCto\-lint\f \- Print a listing of the macro +\fCto_lint\fR, \fCto-lint\fR - Print a listing of the macro expanded and linted LFE code in the files .lint. No object files are produced. Mainly useful for debugging and interest. .IP \bu 2 -\fCto_core0\f, \fCto\-core0\f, \fCto_core\f, -\fCto\-core\f \- Print a listing of the Core Erlang code -before/after being optimised in the files .core. +\fCto_erlang\fR, \fCto-erlang\fR - Print a listing of the Erlang +AST in the file .erl. No object files are produced. Mainly useful for debugging and interest. .IP \bu 2 -\fCto_kernel\f, \fCto\-kernel\f \- Print a listing of the Kernel +\fCto_core0\fR, \fCto-core0\fR, \fCto_core\fR, +\fCto-core\fR - Print a listing of the Core Erlang code before/after +being optimised in the files .core. +No object files are produced. +Mainly useful for debugging and interest. +.IP \bu 2 +\fCto_kernel\fR, \fCto-kernel\fR - Print a listing of the Kernel Erlang code in the files .kernel. No object files are produced. Mainly useful for debugging and interest. .IP \bu 2 -\fCto_asm\f, \fCto\-asm\f \- Print a listing of the Beam code in +\fCto_asm\fR, \fCto-asm\fR - Print a listing of the Beam code in the files .S. No object files are produced. Mainly useful for debugging and interest. .IP \bu 2 -\fC{outdir,Dir}\f, \fCoutdir,Dir\f \- Save the generated files -in director Dir instead of the current directory. +\fC{outdir,Dir}\fR, \fCoutdir,Dir\fR - Save the generated +files in director Dir instead of the current directory. .IP \bu 2 -\fC{i,Dir}\f, \fCi,Dir\f \- Add dir to the list of directories -to be searched when including a file. +\fC{i,Dir}\fR, \fCi,Dir\fR - Add dir to the list of +directories to be searched when including a file. .IP \bu 2 -\fCreport\f \- Print the errors and warnings as they occur. +\fCreport\fR - Print the errors and warnings as they occur. .IP \bu 2 -\fCreturn\f \- Return an extra return field containing Warnings on -success or the errors and warnings in \fC{error,Errors,Warnings}\f +\fCreturn\fR - Return an extra return field containing Warnings on +success or the errors and warnings in \fC{error,Errors,Warnings}\fR when there are errors. .IP \bu 2 -\fCdebug_print\f, \fCdebug\-print\f \- Causes the compiler to +\fCdebug_print\fR, \fCdebug-print\fR - Causes the compiler to print a lot of debug information. .IP \bu 2 -\fCwarnings_as_errors\f, \fCwarnings\-as\-errors\f \- Causes +\fCwarnings_as_errors\fR, \fCwarnings-as-errors\fR - Causes warnings to be treated as errors. .IP \bu 2 -\fCno_export_macros\f, \fCno\-export\-macros\f \- Do not export +\fCno_export_macros\fR, \fCno-export-macros\fR - Do not export macros from modules. .PP If the binary option is given then options that produce listing files will cause the internal formats for that compiler pass to be returned. .PP -Both \fCWarnings\f and \fCErrors\f have the following format: +Both \fCWarnings\fR and \fCErrors\fR have the following format: .IP .nf \fC {FileName,ErrorInfo} -\f +\fR .fi .PP -\fCErrorInfo\f is described below. +\fCErrorInfo\fR is described below. When generating Errors and Warnings the line number is the line of the start of the form in which the error occurred. The file name has been included here to be compatible with the Erlang compiler. As yet there is no extra information about included files. .PP -\fBforms(Forms) \-> CompRet\f +\fBforms(Forms) -> CompRet\fR .PP Is the same as forms(Forms, report). .PP -\fBforms(Forms, Options) \-> CompRet\f +\fBforms(Forms, Options) -> CompRet\fR .PP where .IP .nf \fC -Forms\ =\ sexpr() -CompRet\ =\ BinRet\ |\ ErrRet -BinRet\ =\ {ok,ModBin}\ |\ {ok,ModBin,Warnings} -ModBin\ =\ {ok,ModuleName,Binary}\ |\ {ok,ModuleName,Binary,Warnings} -ErrRet\ =\ error\ |\ {error,ModErr,Errors,Warnings} -ModErr\ =\ {error,Errors,Warnings} -\f +Forms = sexpr() +CompRet = BinRet | ErrRet +BinRet = {ok,ModBin} | {ok,ModBin,Warnings} +ModBin = {ok,ModuleName,Binary} | {ok,ModuleName,Binary,Warnings} +ErrRet = error | {error,ModErr,Errors,Warnings} +ModErr = {error,Errors,Warnings} +\fR .fi .PP Compile the forms as an LFE module returning a binary. -This function takes the same options as \fClfe_comp:file/1/2\f. -When generating Errors and Warnings the "line number" is the index of -the form in which the error occured. +This function takes the same options as \fClfe_comp:file/1/2\fR. +When generating Errors and Warnings the \lqline number\rq is the +index of the form in which the error occurred. .PP -\fBformat_error(Error) \-> Chars\f +\fBformat_error(Error) -> Chars\fR .PP Uses an ErrorDescriptor and returns a deep list of characters which describes the error. @@ -143,21 +148,21 @@ See below. .SH ERROR INFORMATION .PP -The \fCErrorInfo\f mentioned above is the standard -\fCErrorInfo\f structure which is returned from all IO modules.
View file
_service:tar_scm:lfe-2.1.1.tar.gz/doc/man/lfe_docs.3
Added
@@ -0,0 +1,31 @@ +.\" Automatically generated by Pandoc 2.11.2 +.\" +.TH "lfe_docs" "3" "2016" "" "" +.hy +.SH NAME +.PP +lfe_docs - Lisp Flavoured Erlang (LFE) documentation handling. +.SH SYNOPSIS +.PP +This module provides functions to parse docstrings in LFE module sources +in EEP48 format. +.SH EXPORTS +.PP +\fBmake_chunk(Mod, CompilerInfo) -> {ok,DocsChunk}\fR +.PP +Parse a module\cqs docstrings and return a documentation chunk. +.PP +\fBmake_docs_info(Mod, CompilerInfo) -> {ok,DocsInfo}\fR +.PP +Parse a module\cqs docstrings and return the documentation info. +.PP +\fBget_module_docs(Module | Binary) -> {ok,DocsInfo} | +{error,Error}\fR +.PP +Extract the documentation from a module documentation chunk and return +it in the documentation format of the current Erlang version. +.SH SEE ALSO +.PP +\fBlfe_comp(3)\fR, \fBlfe_macro(3)\fR +.SH AUTHORS +Robert Virding.
View file
_service:tar_scm:lfe-1.3.tar.gz/doc/man/lfe_gen.3 -> _service:tar_scm:lfe-2.1.1.tar.gz/doc/man/lfe_gen.3
Changed
@@ -1,61 +1,61 @@ -.\" Automatically generated by Pandoc 1.19.2.1 +.\" Automatically generated by Pandoc 2.11.2 .\" -.TH "lfe_gen" "3" "2008\-2016" "" "" +.TH "lfe_gen" "3" "2008-2016" "" "" .hy .SH NAME .PP -lfe_gen \- Lisp Flavoured Erlang (LFE) dynamic code generator +lfe_gen - Lisp Flavoured Erlang (LFE) dynamic code generator .SH SYNOPSIS .PP This module provides an experimental interface for dynamically generating modules. .SH DATA TYPES .PP -\fBsexpr()\f +\fBsexpr()\fR .PP -An LFE s\-expression, a list structure. +An LFE s-expression, a list structure. .SH EXPORTS .PP -\fBnew_module(Name) \-> ModDef.\f +\fBnew_module(Name) -> ModDef.\fR .PP -\fBadd_exports(Name,Arity, ModDef) \-> ModDef.\f +\fBadd_exports(Name,Arity, ModDef) -> ModDef.\fR .PP -\fBadd_imports(from,Module|Functions, ModDef) \-> ModDef.\f +\fBadd_imports(from,Module|Functions, ModDef) -> ModDef.\fR .PP -\fBadd_imports(rename,Module|Renames, ModDef) \-> ModDef.\f +\fBadd_imports(rename,Module|Renames, ModDef) -> ModDef.\fR .PP -\fBadd_attribute(Attribute, ModDef) \-> ModDef.\f +\fBadd_attribute(Attribute, ModDef) -> ModDef.\fR .PP -\fBadd_form(Form, ModDef) \-> ModDef.\f +\fBadd_form(Form, ModDef) -> ModDef.\fR .PP -\fBbuild_mod(ModDef) \-> Forms.\f +\fBbuild_mod(ModDef) -> Forms.\fR .PP -\fBcompile_mod(Mod) \-> CompRet\f +\fBcompile_mod(Mod) -> CompRet\fR .PP where .IP .nf \fC -CompRet\ =\ BinRet\ |\ ErrRet -BinRet\ =\ {ok,ModuleName,Binary,Warnings} -ErrRet\ =\ {error,Errors,Warnings} -\f +CompRet = BinRet | ErrRet +BinRet = {ok,ModuleName,Binary,Warnings} +ErrRet = {error,Errors,Warnings} +\fR .fi .PP These functions are used to incrementally create a module which can at -the end be compiled by \fCcompile_mod/1\f. +the end be compiled by \fCcompile_mod/1\fR. The various components have the same formats as they do when defining a module in a file. -A simple module which defines one function \fCa/0\f could be defined -with: +A simple module which defines one function \fCa/0\fR could be +defined with: .IP .nf \fC -M0\ =\ lfe_gen:new_module(foo), -M1\ =\ lfe_gen:add_exports(a,0,\ M0), -M2\ =\ lfe_gen:add_form(defun,a,,quote,yes,\ M1), +M0 = lfe_gen:new_module(foo), +M1 = lfe_gen:add_exports(a,0, M0), +M2 = lfe_gen:add_form(defun,a,,quote,yes, M1), lfe_gen:compile_mod(M2) -\f +\fR .fi .SH EXAMPLE .PP @@ -69,17 +69,17 @@ .IP .nf \fC -\-module(Name). -\-export(<param1>/1,...). +-module(Name). +-export(<param1>/1,...). -<param1>(Feature)\ \-> -\ \ \ \ case\ Feature\ of -\ \ \ \ \ \ \ \ <feature1>\ \->\ <value1>; -\ \ \ \ \ \ \ \ ... -\ \ \ \ \ \ \ \ _\ \->\ erlang:error({unknown_feature,<param1>,Feature) -\ \ \ \ end. +<param1>(Feature) -> + case Feature of + <feature1> -> <value1>; + ... + _ -> erlang:error({unknown_feature,<param1>,Feature) + end. \&... -\f +\fR .fi .PP but generating it and compiling it directly in memory without generating @@ -88,51 +88,51 @@ .IP .nf \fC -Params\ =\ {Parameter,{Feature,Value}} -\f +Params = {Parameter,{Feature,Value}} +\fR .fi .PP The equivalent LFE code which we will be generating is: .IP .nf \fC -(defmodule\ Name -\ \ (export\ (<param1>\ 1)\ (<param2>\ 1)\ ...\ )) +(defmodule Name + (export (<param1> 1) (<param2> 1) ... )) -(defun\ <param1>\ (f) -\ \ (case\ f -\ \ \ \ (\aq<feature1>\ \aq<value1>) -\ \ \ \ ... -\ \ \ \ (f\ (:\ erlang\ error\ (tuple\ \aqunknown_feature\ \aq<param1>\ f))))) +(defun <param1> (f) + (case f + (\aq<feature1> \aq<value1>) + ... + (f (: erlang error (tuple \aqunknown_feature \aq<param1> f))))) \&... -\f +\fR .fi .PP The following code builds and compiles a module from the parameter data: .IP .nf \fC -make_module(Name,\ Params)\ \-> -\ \ \ \ Mod0\ =\ lfe_gen:new_module(Name), -\ \ \ \ Exps\ =\ lists:map(fun\ ({Param,_})\ \->\ Param,1\ end,\ Params), -\ \ \ \ Mod1\ =\ lfe_gen:add_exports(Exps,\ Mod0), -\ \ \ \ Mod2\ =\ make_funcs(Params,\ Mod1), -\ \ \ \ lfe_gen:compile_mod(Mod2). +make_module(Name, Params) -> + Mod0 = lfe_gen:new_module(Name), + Exps = lists:map(fun ({Param,_}) -> Param,1 end, Params), + Mod1 = lfe_gen:add_exports(Exps, Mod0), + Mod2 = make_funcs(Params, Mod1), + lfe_gen:compile_mod(Mod2). -make_funcs({Param,Fs}|Ps,\ Mod)\ \-> -\ \ \ \ %%\ Define\ catch\-all\ which\ generates\ more\ explicit\ exit\ value. -\ \ \ \ CatchAll\ =\ f,\aq:\aq,erlang,error, -\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ tuple,unknown_feature,quote,Param,f, -\ \ \ \ %%\ Build\ case\ clauses -\ \ \ \ Fold\ =\ fun\ ({Feature,Value},\ Cls)\ \-> -\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ quote,Feature,quote,Value|Cls -\ \ \ \ \ \ \ \ \ \ \ end -\ \ \ \ Cls\ =\ lists:foldr(Fold,\ CatchAll,\ Params), -\ \ \ \ %%\ Build\ function. -\ \ \ \ Func\ =\ defun,Param,f,\aqcase\aq,f,Cls, -\ \ \ \ make_funcs(Ps,\ lfe_gen:add_form(Func,\ Mod)); -make_funcs(,\ Mod)\ \->\ Mod.\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ %All\ done -\f +make_funcs({Param,Fs}|Ps, Mod) -> + %% Define catch-all which generates more explicit exit value. + CatchAll = f,\aq:\aq,erlang,error, + tuple,unknown_feature,quote,Param,f, + %% Build case clauses + Fold = fun ({Feature,Value}, Cls) -> + quote,Feature,quote,Value|Cls + end + Cls = lists:foldr(Fold, CatchAll, Params), + %% Build function. + Func = defun,Param,f,\aqcase\aq,f,Cls, + make_funcs(Ps, lfe_gen:add_form(Func, Mod)); +make_funcs(, Mod) -> Mod. %All done +\fR .fi .PP This module could be generated and then be loaded into the system by @@ -140,30 +140,30 @@ .IP .nf \fC -{ok,ModuleName,Binary,Warnings}\ =\ make_module(Name,\ Params),
View file
_service:tar_scm:lfe-1.3.tar.gz/doc/man/lfe_guide.7 -> _service:tar_scm:lfe-2.1.1.tar.gz/doc/man/lfe_guide.7
Changed
@@ -1,14 +1,28 @@ -.\" Automatically generated by Pandoc 1.19.2.1 +.\" Automatically generated by Pandoc 2.19.1 .\" -.TH "lfe_guide" "7" "2008\-2016" "" "" +.\" Define V font for inline verbatim, using C font in formats +.\" that render this, and otherwise B font. +.ie "\fCBx\f"x" \{\ +. ftr V B +. ftr VI BI +. ftr VB B +. ftr VBI BI +.\} +.el \{\ +. ftr V CR +. ftr VI CI +. ftr VB CB +. ftr VBI CBI +.\} +.TH "lfe_guide" "7" "2008-2020" "" "" .hy .SH NAME .PP -lfe_guide \- Lisp Flavoured Erlang User Guide -.SH SYNPOSIS +lfe_guide - Lisp Flavoured Erlang User Guide +.SH SYNOPSIS .PP -Note: {{ ... -}} is use to denote optional syntax. +Note: {{ \&... +}} is used to denote optional syntax. .SH LITERALS AND SPECIAL SYNTACTIC RULES .SS Integers .PP @@ -18,56 +32,56 @@ .IP .nf \fC -\ \ 1234\ \-123\ 0 -\f + 1234 -123 0 +\fR .fi .IP \bu 2 Binary notation: .IP .nf \fC -\ \ #b0\ #b10101\ #b\-1100 -\f + #b0 #b10101 #b-1100 +\fR .fi .IP \bu 2 Binary notation (alternative form): .IP .nf \fC -\ \ #*0\ #b*10101\ #*\-1100 -\f + #*0 #*10101 #*-1100 +\fR .fi .IP \bu 2 Octal notation: .IP .nf \fC -\ \ #o377\ #o\-111 -\f + #o377 #o-111 +\fR .fi .IP \bu 2 Explicitly decimal notation: .IP .nf \fC -\ \ #d1234\ #d\-123\ #d0 -\f + #d1234 #d-123 #d0 +\fR .fi .IP \bu 2 Hexadecimal notation: .IP .nf \fC -\ \ #xc0ffe\ 0x\-01 -\f + #xc0ffe #x-01 +\fR .fi .IP \bu 2 Notation with explicit base (up to 36): .IP .nf \fC -\ \ #2r1010\ #8r377\ #36rhelloworld -\f + #2r1010 #8r377 #36rhelloworld +\fR .fi .IP \bu 2 Character notation (the value is the Unicode code point of the @@ -75,53 +89,51 @@ .IP .nf \fC -\ \ #\\a\ #\\$\ #\\ä -\f + #\rsa #\rs$ #\rs\:a +\fR .fi .IP \bu 2 Character notation with the value in hexadecimal: .IP .nf \fC -\ \ #\\x1f42d; -\f + #\rsx1f42d; +\fR .fi .PP In all these forms, the case of the indicating letter is not -significant, i.e. -\fC#b1010\f and \fC#B1010\f are identical as are -\fC#16rf00\f and \fC#16Rf00\f. -.PP -Similarly, the case is not significant for digits beyond 9 (i.e. -\aqa\aq, \aqb\aq, \aqc\aq, \&... for number bases larger -than 10), e.g. -\fC#xabcd\f is the same as \fC#xABCD\f and can even be mixed in -the same number, e.g. -\fC#36rHelloWorld\f is valid and the same number as -\fC#36Rhelloworld\f and \fC#36rHELLOWORLD\f. +significant, i.e.\ \fV#b1010\fR and \fV#B1010\fR are identical +as are \fV#16rf00\fR and \fV#16Rf00\fR. +.PP +Similarly, the case is not significant for digits beyond 9 (i.e.\ `a', +`b', `c', \&... +for number bases larger than 10), e.g.\ \fV#xabcd\fR is the same as +\fV#xABCD\fR and can even be mixed in the same number, +e.g.\ \fV#36rHelloWorld\fR is valid and the same number as +\fV#36Rhelloworld\fR and \fV#36rHELLOWORLD\fR. .PP The character notation using hexadecimal code representation -(\fC#\\x....;\f) is basically the same thing as the regular -hexadecimal notation \fC#x...\f except that it conveys to the reader -that a character is intended and that it does a sanity check on the -value (e.g. -negative numbers and value outside the Unicode range are not permitted). +(\fV#\rsx....;\fR) is basically the same thing as the regular +hexadecimal notation \fV#x...\fR except that it conveys to the +reader that a character is intended and that it does a sanity check on +the value (e.g.\ negative numbers and value outside the Unicode range +are not permitted). .SS Floating point numbers .PP There is only one type of floating point numbers and the literals are -written in the usual way, e.g. -these are all valid floating point numbers: +written in the usual way, e.g.\ these are all valid floating point +numbers: .IP .nf \fC -1.0\ +1.0\ \-1.0\ 1.0e10\ 1.111e\-10 -\f +1.0 +1.0 -1.0 1.0e10 1.111e-10 +\fR .fi .PP -The one thing to watch out for is that you cannot omit the the part -before or after the decimal point if it is zero. +The one thing to watch out for is that you cannot omit the part before +or after the decimal point if it is zero. E.g. -the following are not valid forms: \fC100.\f or \fC\&.125\f. +the following are not valid forms: \fV100.\fR or \fV.125\fR. .SS Strings .PP There are two forms of strings: list strings and binary strings. @@ -131,30 +143,32 @@ from a certain set of numbers that are considered valid characters) but they have their own syntax for literals (which will also be used for integer lists as an output representation if the list contents looks -like it is meant to be a string): "any text between double quotes where -" and other special characters like \fC\\n\f can be escaped". +like it is meant to be a string): \lqany text between double quotes +where \dq and other special characters like \fV\rsn\fR can be +escaped\rq. .PP As a special case you can also write out the character number in the -form \fC\\xHHH;\f (where "HHH" is an integer in hexadecimal -notation), e.g. -\fC"\\x61;\\x62;\\x63;"\f is a complicated way of writing -\fC"abc"\f.
View file
_service:tar_scm:lfe-1.3.tar.gz/doc/man/lfe_io.3 -> _service:tar_scm:lfe-2.1.1.tar.gz/doc/man/lfe_io.3
Changed
@@ -1,10 +1,10 @@ -.\" Automatically generated by Pandoc 1.19.2.1 +.\" Automatically generated by Pandoc 2.11.2 .\" -.TH "lfe_io" "3" "2008\-2016" "" "" +.TH "lfe_io" "3" "2008-2019" "" "" .hy .SH NAME .PP -lfe_io \- Lisp Flavoured Erlang (LFE) io functions +lfe_io - Lisp Flavoured Erlang (LFE) io functions .SH SYNOPSIS .PP This module provides a standard set of io functions for LFE. @@ -20,132 +20,145 @@ an error if the form is wrong. .SH DATA TYPES .PP -\fBchars() = char() | chars()\f +\fBchars() = char() | chars()\fR .PP -\fBfilesexpr() = {Sexpr,Line}\f +\fBfilesexpr() = {Sexpr,Line}\fR .PP -This is the format returned by \fClfe_io:parse_file/1\f and is used +This is the format returned by \fClfe_io:parse_file/1\fR and is used by the compiler to give better error information. .SH EXPORTS .PP -\fBread(IoDevice, Prompt) \-> {ok,Sexpr} | {error,ErrorInfo}\f +\fBread(IoDevice, Prompt) -> {ok,Sexpr} | {error,ErrorInfo} | +eof\fR .PP -Read an s\-expr from the standard input (IoDevice) with a prompt -(Prompt). -Note that this is not line\-oriented in that it stops as soon as it has +Read an s-expr from the standard input (\fCIoDevice\fR) with a +prompt (\fCPrompt\fR). +Note that this is not line-oriented in that it stops as soon as it has consumed enough characters. .PP -\fBread_line(IoDevice, Prompt) \-> {ok,Sexpr} | -{error,ErrorInfo}\f +\fBread_line(IoDevice, Prompt) -> {ok,Sexpr} | {error,ErrorInfo} | +eof\fR .PP -Read an s\-expr from the standard input (IoDevice) with a prompt -(Prompt). -Note that this is line\-oriented in that it reads whole lines discarding -left\-over characters in the last line. +Read an s-expr from the standard input (\fCIoDevice\fR) with a +prompt (\fCPrompt\fR). +Note that this is line-oriented in that it reads whole lines discarding +left-over characters in the last line. .PP -\fBread_string(String) \-> {ok,Sexpr} | {error,ErrorInfo}\f +\fBread_string(String) -> {ok,Sexpr} | {error,ErrorInfo}\fR .PP -Read an s\-expr from String. +Read an s-expr from \fCString\fR. +Note that this only reads from \fCString\fR discarding left-over +characters at the end of the string. .PP -\fBprint(IoDevice, Sexpr) \-> ok\f +\fBprint(IoDevice, Sexpr) -> ok\fR .PP -Print the s\-expr Sexpr to the standard output (IoDevice). +Print the s-expr \fCSexpr\fR to the standard output +(\fCIoDevice\fR). .PP -\fBprint1(Sexpr) \-> DeepCharList\f +\fBprint1(Sexpr) -> DeepCharList\fR .PP -Return the list of characters which represent the s\-expr Sexpr. +Return the list of characters which represent the s-expr +\fCSexpr\fR. .PP -\fBprettyprint1(Sexpr) \-> DeepCharList\f +\fBprettyprint(IoDevice, Sexpr) -> ok\fR .PP -\fBprettyprint1(Sexpr, Depth) \-> DeepCharList\f +Pretty print the s-expr \fCSexpr\fR to the standard output +(\fCIoDevice\fR). .PP -\fBprettyprint1(Sexpr, Depth, Indentation) \-> DeepCharList\f +\fBprettyprint1(Sexpr) -> DeepCharList\fR .PP -\fBprettyprint1(Sexpr, Depth, Indentation, LineLength) \-> -DeepCharList\f +\fBprettyprint1(Sexpr, Depth) -> DeepCharList\fR .PP -Return the lost of characters which represents the prettyprinted s\-expr -\fCSexpr\f. -Assume we start at indentation Indentation or 0. +\fBprettyprint1(Sexpr, Depth, Indentation) -> DeepCharList\fR .PP -\fBformat(IoDevice, Format, Args) \-> ok\f +\fBprettyprint1(Sexpr, Depth, Indentation, LineLength) -> +DeepCharList\fR .PP -\fBfwrite(IoDevice, Format, Args) \-> ok\f +Return the list of characters which represents the prettyprinted s-expr +\fCSexpr\fR. +Default values for \fCDepth\fR is 30, \fCIndentation\fR is 0 and +\fCLineLength\fR is 80. .PP -\fBformat1(Format, Args) \-> DeepCharList\f +\fBformat(IoDevice, Format, Args) -> ok\fR .PP -\fBfwrite1(Format, Args) \-> DeepCharList\f +\fBfwrite(IoDevice, Format, Args) -> ok\fR +.PP +\fBformat1(Format, Args) -> DeepCharList\fR +.PP +\fBfwrite1(Format, Args) -> DeepCharList\fR .PP Print formatted output. The following commands are valid in the format string: .IP \bu 2 -\fB~w, ~W\f \- print LFE terms +\fB\tiw, \tiW\fR - print LFE terms .IP \bu 2 -\fB~p, ~P\f \- prettyprint LFE terms +\fB\tip, \tiP\fR - prettyprint LFE terms .IP \bu 2 -\fB~s\f \- print a string +\fB\tis\fR - print a string .IP \bu 2 -\fB~e, ~f, ~g\f \- print floats +\fB\tie, \tif, \tig\fR - print floats .IP \bu 2 -\fB~b, ~B\f \- based integers +\fB\tib, \tiB\fR - based integers .IP \bu 2 -\fB~x, ~X\f \- based integers with a prefix +\fB\tix, \tiX\fR - based integers with a prefix .IP \bu 2 -\fB~+, ~#\f \- based integers in vanilla erlang format +\fB\ti+, \ti#\fR - based integers in vanilla erlang format .IP \bu 2 -\fB~c, ~n, ~i\f +\fB\tic, \tin, \tii\fR .PP -Currently they behave as for vanilla erlang except that \fC~w\f, -\fC~W\f, \fC~p\f, \fC~P\f print the terms as LFE sexprs. +Currently they behave as for vanilla erlang except that +\fC\tiw\fR, \fC\tiW\fR, \fC\tip\fR, \fC\tiP\fR +print the terms as LFE sexprs. .PP -\fBread_file(FileName) \-> {ok,Sexpr} | {error,ErrorInfo}\f +\fBread_file(FileName) -> {ok,Sexpr} | {error,ErrorInfo}\fR .PP -Read the file Filename returning a list of s\-exprs (as it should be). +Read the file \fCFilename\fR returning a list of s-exprs (as it +should be). .PP -\fBparse_file(FileName) \-> {ok,FileSexpr} | {error,ErrorInfo}\f +\fBparse_file(FileName) -> {ok,FileSexpr} | {error,ErrorInfo}\fR .PP where .IP .nf \fC -FileSexpr\ =\ filesexpr() -\f +FileSexpr = filesexpr() +\fR .fi .PP -Read the file Filename returning a list of pairs containing s\-expr and -line number of the start of the s\-expr. +Read the file \fCFilename\fR returning a list of pairs containing +s-expr and line number of the start of the s-expr. .PP -\fBscan_sexpr(Cont, Chars ,Line) \-> -{done,Ret,RestChars}|{more,Cont1}\f +\fBscan_sexpr(Cont, Chars ,Line) -> +{done,Ret,RestChars}|{more,Cont1}\fR .PP -This is a re\-entrant call which scans tokens from the input and returns +This is a re-entrant call which scans tokens from the input and returns a parsed sepxr. If there are enough characters to parse a sexpr or it detects and error -then it returns \fC{done,...}\f otherwise it returns -\fC{more,Cont}\f where \fCCont\f is used in the next call to -\fCscan_sexpr\f with more characters to try and parse a sexpr. +then it returns \fC{done,...}\fR otherwise it returns +\fC{more,Cont}\fR where \fCCont\fR is used in the next call to +\fCscan_sexpr\fR with more characters to try and parse a sexpr. This is continued until a sexpr has been parsed. -\fCCont\f is initially \fC\f. +\fCCont\fR is initially \fC\fR. .PP It is not designed to be called directly by an application but used through the i/o system where it can typically be called in an application by: .PP -\fCio:request(In,\ {get_until,unicode,Prompt,Module,scan_sexpr,Line})\f +\fCio:request(In, {get_until,unicode,Prompt,Module,scan_sexpr,Line})\fR .SH ERROR INFORMATION
View file
_service:tar_scm:lfe-1.3.tar.gz/doc/man/lfe_lib.3 -> _service:tar_scm:lfe-2.1.1.tar.gz/doc/man/lfe_lib.3
Changed
@@ -1,10 +1,10 @@ -.\" Automatically generated by Pandoc 1.19.2.1 +.\" Automatically generated by Pandoc 2.11.2 .\" -.TH "lfe_lib" "3" "2008\-2016" "" "" +.TH "lfe_lib" "3" "2008-2016" "" "" .hy .SH NAME .PP -lfe_lib \- Lisp Flavoured Erlang (LFE) library module +lfe_lib - Lisp Flavoured Erlang (LFE) library module .SH SYNOPSIS .PP This module contains a collection of library functions for implementing @@ -12,22 +12,22 @@ They are generally not called by the user. .SH EXPORTS .PP -\fBnew_env() \-> Env.\f +\fBnew_env() -> Env.\fR .PP Create a new environment for the evaluator. .PP -\fBadd_env(Env1, Env2) \-> Env.\f +\fBadd_env(Env1, Env2) -> Env.\fR .PP Add environment Env1 to Env2 such that Env1 shadows Env2. .PP -\fBis_erl_bif(Name, Arity) \-> bool().\f +\fBis_erl_bif(Name, Arity) -> bool().\fR .PP -\fBis_guard_bif(Name, Arity) \-> bool().\f +\fBis_guard_bif(Name, Arity) -> bool().\fR .PP Test whether a Name/Arity is a BIF or guard BIF. This works for functions and operators. .PP -\fBis_core_form(Name) \-> bool().\f +\fBis_core_form(Name) -> bool().\fR .PP Test whether Name is one the LFE core forms. .SH AUTHORS
View file
_service:tar_scm:lfe-1.3.tar.gz/doc/man/lfe_macro.3 -> _service:tar_scm:lfe-2.1.1.tar.gz/doc/man/lfe_macro.3
Changed
@@ -1,10 +1,10 @@ -.\" Automatically generated by Pandoc 1.19.2.1 +.\" Automatically generated by Pandoc 2.11.2 .\" -.TH "lfe_macro" "3" "2008\-2016" "" "" +.TH "lfe_macro" "3" "2008-2020" "" "" .hy .SH NAME .PP -lfe_macro \- Lisp Flavoured Erlang (LFE) macro expander +lfe_macro - Lisp Flavoured Erlang (LFE) macro expander .SH SYNOPSIS .PP This module provides an interface to the LFE macro expander. @@ -12,80 +12,118 @@ used by applications explicitly wanting to handle a file. .SH DATA TYPES .PP -\fBsexpr()\f +\fBsexpr()\fR .PP -An LFE s\-expression, a list structure. +An LFE s-expression, a list structure. .PP -\fBfilesexpr() = {Sexpr,Line}\f +\fBfilesexpr() = {Sexpr,Line}\fR .PP -This is the format returned by \fClfe_io:parse_file/1\f and is used +This is the format returned by \fClfe_io:parse_file/1\fR and is used by the compiler to give better error information. .PP -\fBenv()\f +\fBenv()\fR .PP This is an macro and evaluation environment as created by -\fClfe_lib:new_env()\f. +\fClfe_lib:new_env()\fR. +.PP +\fBmac_state()\fR +.PP +This is the internal state used by the macro expander. .SH EXPORTS .PP -\fBexpand_forms(FileSexpr, Env) \-> ExpRet\f +\fBexpand_expr(Sexpr, Env) -> {yes,Exp} | no.\fR +.PP +\fBexpand_expr_1(Sexpr, Env) -> {yes,Exp} | no.\fR .PP where .IP .nf \fC -\ \ FileSexpr\ =\ filesexpr() -\ \ Env\ =\ env() -\ \ ExpRet\ =\ {yes,FileSexpr,Env,Warnings}\ |\ {error,Errors,Warnings} -\f +Sexpr = Exp = sexpr() +Env = env() +\fR .fi .PP -\fBmacro_forms(FileSexpr, Env) \-> {FileSexpr,Env}.\f +Test if the top s-expression here is a macro call, if so expand it and +return {yes,Expansion}, if not then return no. +\fCexpand_expr/2\fR will expand the top s-expression as much as +possible while \fCexpand_expr_1/2\fR will only try it once. +These functions use the macro definitions in the environment and the +standard pre-defined macros. +.PP +\fBexpand_expr_all(Sexpr, Env) -> Sexpr.\fR .PP where .IP .nf \fC -FileSexpr\ =\ filesexpr() -Env\ =\ env() -\f +Sexpr = sexpr() +Env = env() +\fR .fi .PP -\fBexpand_expr_all(Sexpr, Env) \-> Sexpr.\f +Expand all macros in Sexpr either using the definitions in Env or just +the default macros. +Note that any eventual new macro definitions will be lost. +.PP +\fBexpand_form_init(Deep, Keep) -> MacState\fR .PP where .IP .nf \fC -Sexpr\ =\ sexpr() -Env\ =\ env() -\f + Deep = boolean() + Keep = boolean() + MacState = mac_state() +\fR .fi .PP -Expand all macros in Sexpr either using the definitions in Env or just -the default macros. -Note that any eventual new macro definitions will be lost. +Create an internal macro state. +\fCDeep\fR determines whether the form is to be expanded internally +at depth and \fCKeep\fR whether macro definition forms are to be +kept. .PP -\fBexpand_expr(Sexpr, Env) \-> {yes,Exp} | no.\f +\fBexpand_fileforms(FileForm, Env, Deep, Keep) -> ExpRet\fR .PP -\fBexpand_expr_1(Sexpr, Env) \-> {yes,Exp} | no.\f +\fBexpand_fileforms(FileForm, Env, MacState) -> ExpRet\fR .PP where .IP .nf \fC -Sexpr\ =\ Exp\ =\ sexpr() -Env\ =\ env() -\f + FileForm = filesexpr() + Env = env() + Deep = boolean() + Keep = boolean() + MacState = mac_state() + ExpRet = {yes,FileSexpr,Env,Warnings} | + {error,Errors,Warnings} +\fR .fi .PP -Test if the top s\-expression here is a macro call, if so expand it and -return {yes,Expansion}, if not then return no. -\fCexpand_expr/2\f will expand the top s\-expression as much as -possible while \fCexpand_expr_1/2\f will only try it once. -These functions use the macro definitions in the environment and the -standard pre\-defined macros. +expand a sequence of file forms. +.PP +\fBexpand_form(Form, Line, Env, MacState) -> RetState\fR +.PP +\fBexpand_fileform(FileForm, Env, MacState) -> RetState\fR +.PP +where +.IP +.nf +\fC + Form = sexpr() + FileForm = filesexpr() + Line = integer() + Env = env() + MacState = mac_state() + RetState = {ok,Form,Env,Macstate} | + {error,Errors,Warnings,MacState} +\fR +.fi +.PP +Expand a file form using the environment and macro state. .SH SEE ALSO .PP -\fBlfe_comp(3)\f, \fBlfe_gen(3)\f +\fBlfe_comp(3)\fR, \fBlfe_gen(3)\fR .SH AUTHORS Robert Virding.
View file
_service:tar_scm:lfe-1.3.tar.gz/doc/man/lfe_types.7 -> _service:tar_scm:lfe-2.1.1.tar.gz/doc/man/lfe_types.7
Changed
@@ -1,11 +1,11 @@ -.\"t -.\" Automatically generated by Pandoc 1.19.2.1 +'\" t +.\" Automatically generated by Pandoc 2.11.2 .\" -.TH "lfe_types" "7" "2016" "" "" +.TH "lfe_types" "7" "2021" "" "" .hy .SH NAME .PP -lfe_types \- LFE Types and Functions Specifications +lfe_types - LFE Types and Functions Specifications .SH TYPES .PP This is a description of the type syntax. @@ -20,119 +20,135 @@ T} _ T{ -\fC(none)\f +\fC(none)\fR T}@T{ -\fCnone()\f +\fCnone()\fR T} T{ -\fC(any)\f +\fC(any)\fR T}@T{ -\fCany()\f +\fCany()\fR T} T{ -\fC(atom)\f +\fC(atom)\fR T}@T{ -\fCatom()\f +\fCatom()\fR T} T{ -\fC(integer)\f +\fC(integer)\fR T}@T{ -\fCinteger()\f +\fCinteger()\fR T} T{ -\fC(range\ i1\ i2)\f +\fC(range i1 i2)\fR T}@T{ -\fCI1..I2\f +\fCI1..I2\fR T} T{ -\fC(float)\f +\fC(float)\fR T}@T{ -\fCfloat()\f +\fCfloat()\fR T} T{ -\fC(bitstring\ m\ n)\f +\fC(bitstring m n)\fR T}@T{ -\fC<<_:M,_:_*N>>\f +\fC<<_:M,_:_*N>>\fR T} T{ -\fC(binary)\f +\fC(binary)\fR T}@T{ -\fC<<_:0,_:_*8>>\f +\fC<<_:0,_:_*8>>\fR T} T{ -\fC(bitstring)\f +\fC(bitstring)\fR T}@T{ -\fC<<_:0,_:_*1>>\f +\fC<<_:0,_:_*1>>\fR T} T{ -\fC\&...\f +\fC...\fR T}@T{ -\fC\&...\f +\fC...\fR T} T{ -\fC(lambda\ any\ <type>)\f +\fC(lambda any <type>)\fR T}@T{ -\fCfun((...)\ \->\ <type>)\f +\fCfun((...) -> <type>)\fR T} T{ -\fC(lambda\ ()\ <type>)\f +\fC(lambda () <type>)\fR T}@T{ -\fCfun(()\ \->\ <type>)\f +\fCfun(() -> <type>)\fR T} T{ -\fC(lambda\ (<tlist>)\ <type>)\f +\fC(lambda (<tlist>) <type>)\fR T}@T{ -\fCfun((<tlist>)\ \->\ <type>)\f +\fCfun((<tlist>) -> <type>)\fR T} T{ -\fC(map)\f +\fC(map)\fR T}@T{ -\fCmap()\f +\fCmap()\fR T} T{ -\fC(map\ <pairlist>)\f +\fC#M()\fR T}@T{ -\fC#{<pairlist>}\f +\fC#{}\fR T} T{ -\fC(tuple)\f +\fC#M(<key> <value> ...)\fR T}@T{ -\fCtuple()\f +\fC#{<pairlist>}\fR T} T{ -\fC(tuple\ <tlist>)\f +\fC(tuple)\fR T}@T{ -\fC{<tlist>}\f +\fCtuple()\fR T} T{ -\fC(UNION\ <tlist>)\f +\fC#()\fR T}@T{ -\fC<type>\ |\ <type>\f +\fC{}\fR +T} +T{ +\fC#(<tlist>)\fR +T}@T{ +\fC{<tlist>}\fR +T} +T{ +\fC(UNION <tlist>)\fR +T}@T{ +\fC<type> | <type>\fR T} .TE .PP Apart from the predefined types in the Erlang type system we also have the following predefined types which cannot be redefined: -\fCUNION\f, \fCcall\f, \fClambda\f and \fCrange\f. -The usage of \fCbitstring\f, \fCtuple\f and \fCmap\f have +\fCUNION\fR, \fCcall\fR, \fClambda\fR and \fCrange\fR. +The usage of \fCbitstring\fR, \fCtuple\fR and \fCmap\fR have also been extended. .PP -The general form of bitstrings is \fC(bitstring\ m\ n)\f which -denotes a bitstring which starts with \fCm\f bits and continues with -segments of \fCn\f bits. -\fC(binary)\f is a short form for a sequence of bytes while -\fC(bitstring)\f is a short form for a sequence of bits. +Note that the type \fC#M()\fR is the empty map and the type +\fC#()\fR is the empty tuple. +We can still use the older \fC(map <key valuelist>)\fR and +\fC(tuple <tlist>)\fR formats when declaring types for maps and +tuples. +.PP +The general form of bitstrings is \fC(bitstring m n)\fR which +denotes a bitstring which starts with \fCm\fR bits and continues +with segments of \fCn\fR bits. +\fC(binary)\fR is a short form for a sequence of bytes while +\fC(bitstring)\fR is a short form for a sequence of bits. There is currently no short form for an empty binary, -\fC(bitstring\ 0\ 0)\f must be used. -.SS Type Declarations of User\-Defined Types +\fC(bitstring 0 0)\fR must be used. +.SS Type Declarations of User-Defined Types .PP -\fB(deftype (type\-name) type\-def)\f +\fB(deftype (type-name) type-def)\fR .PP -\fB(defopaque (type\-name) type\-def)\f +\fB(defopaque (type-name) type-def)\fR .PP -\fB(deftype (type\-name par1 par2) type\-def)\f +\fB(deftype (type-name par1 par2) type-def)\fR .PP -\fB(defopaque (type\-name par1 par2) type\-def)\f +\fB(defopaque (type-name par1 par2) type-def)\fR .PP For unparameterised types the parentheses around the type name are
View file
_service:tar_scm:lfe-1.3.tar.gz/doc/man/lfescript.1 -> _service:tar_scm:lfe-2.1.1.tar.gz/doc/man/lfescript.1
Changed
@@ -1,10 +1,10 @@ -.\" Automatically generated by Pandoc 1.19.2.1 +.\" Automatically generated by Pandoc 2.11.2 .\" -.TH "lfescript" "1" "2013\-2016" "" "" +.TH "lfescript" "1" "2013-2016" "" "" .hy .SH NAME .PP -lfescript \- Lisp Flavoured Erlang (LFE) scripting support +lfescript - Lisp Flavoured Erlang (LFE) scripting support .SH SYNOPSIS .PP lfescript provides support for running short LFE programs without having @@ -12,24 +12,24 @@ arguments. .SH EXPORTS .PP -\fBscript\-name script\-arg1 script\-arg2 ...\f +\fBscript-name script-arg1 script-arg2 \&...\fR .PP -\fBlfescript lfescript\-flags script\-name script\-arg1 script\-arg2 -\&...\f +\fBlfescript lfescript-flags script-name script-arg1 script-arg2 +\&...\fR .PP lfescript runs a script written in LFE. .PP -\fBlfescript:script_name() \-> File\f +\fBlfescript:script_name() -> File\fR .PP Types: .IP .nf \fC -File\ =\ filename() -\f +File = filename() +\fR .fi .PP -The \fCscript_name/0\f function returns the name of the lfescript +The \fCscript_name/0\fR function returns the name of the lfescript being executed. If the function is invoked outside the context of an lfescript, the behavior is undefined. @@ -39,28 +39,28 @@ .IP .nf \fC -$\ cat\ factorial -#!\ /usr/bin/env\ lfescript -;;\ \-*\-\ mode:\ lfe\ \-*\- -;;!\ \-smp\ enable\ \-sname\ factorial\ \-mnesia\ debug\ verbose +$ cat factorial +#! /usr/bin/env lfescript +;; -*- mode: lfe -*- +;;! -smp enable -sname factorial -mnesia debug verbose -(defun\ main -\ \ ((list\ string) -\ \ \ (try -\ \ \ \ \ \ \ (let*\ ((n\ (list_to_integer\ string)) -\ \ \ \ \ \ \ \ \ \ \ \ \ \ (f\ (fac\ n))) -\ \ \ \ \ \ \ \ \ (lfe_io:format\ "factorial\ ~w\ =\ ~w\\n"\ (list\ n\ f))) -\ \ \ \ \ (catch -\ \ \ \ \ \ \ ((tuple\ _\ _\ _)\ (usage))))) -\ \ (_\ (usage))) +(defun main + ((list string) + (try + (let* ((n (list_to_integer string)) + (f (fac n))) + (lfe_io:format \dqfactorial \tiw = \tiw\rsn\dq (list n f))) + (catch + ((tuple _ _ _) (usage))))) + (_ (usage))) -(defun\ fac -\ \ (0\ 1) -\ \ (n\ (*\ n\ (fac\ (\-\ n\ 1))))) +(defun fac + (0 1) + (n (* n (fac (- n 1))))) -(defun\ usage\ () -\ \ (lfe_io:format\ "usage:\ factorial\ integer\\n"\ ())) -\f +(defun usage () + (lfe_io:format \dqusage: factorial integer\rsn\dq ())) +\fR .fi .PP The header of the LFE script is different from a normal LFE module. @@ -73,15 +73,15 @@ .IP .nf \fC -;;!\ \-smp\ enable\ \-sname\ factorial\ \-mnesia\ debug\ verbose -\f +;;! -smp enable -sname factorial -mnesia debug verbose +\fR .fi .PP In the example the second line is an optional directive to Emacs which causes it to enter LFE mode when editing the script file. .PP The rest of the file contains LFE source code. -It must always the function \fCmain/1\f. +It must always contain the function \fCmain/1\fR. When the script is run this function will be called with a list of strings representing the arguments with which the script was called. It is possible to define, include and use macros in the source code. @@ -90,15 +90,15 @@ If there are errors the script will not run and it will terminate with exit status 127. Otherwise the code will be interpreted. -If the function \fCmain/1\f returns successfully then the exit +If the function \fCmain/1\fR returns successfully then the exit status for the script will be 0 but if an exception is raised then exit status will be 127. .SH OPTIONS .PP The following option is accepted by lfescript .IP \bu 2 -\fC\-s\f \- Only perform a syntactic and semantic check of the -script file. +\fC-s\fR - Only perform a syntactic and semantic check of the script +file. Warnings and errors (if any) are written to the standard output, but the script will not be run. The exit status will be 0 if there were no errors, and 127 otherwise. @@ -106,21 +106,21 @@ Unrecognised options are ignored. .SH ENVIRONMENT VARIABLES .PP -\fBLFESCRIPT_EMULATOR\f +\fBLFESCRIPT_EMULATOR\fR .PP The command used to start the emulator. -Default is \aqerl\aq. +Default is `erl'. This can be useful for passing arguments into the emulator, for example .IP .nf \fC -LFESCRIPT_EMULATOR="erl\ \-pa\ sune" -\f +LFESCRIPT_EMULATOR=\dqerl -pa sune\dq +\fR .fi .PP will add the directory sune to the code path. .SH SEE ALSO .PP -\fBlfe(1)\f, \fBlfe_guide(7)\f +\fBlfe(1)\fR, \fBlfe_guide(7)\fR .SH AUTHORS Robert Virding.
View file
_service:tar_scm:lfe-1.3.tar.gz/doc/src/lfe.1.md -> _service:tar_scm:lfe-2.1.1.tar.gz/doc/src/lfe.1.md
Changed
@@ -1,6 +1,6 @@ % lfe(1) % Robert Virding -% 2008-2016 +% 2008-2020 # NAME @@ -40,14 +40,6 @@ Clear the REPL output. -**(doc | describe Mod)** - -**(doc | describe Mod:Mac)** - -**(doc | describe Mod:Fun/Arity)** - -Print out documentation of a module/macro/function. - **(ec File Options)** Compile and load an Erlang file. @@ -69,11 +61,23 @@ Print usage info. +**(h Mod)** + +**(h Mod Mac)** + +**(h Mod Fun Arity)** + +Print out help information of a module/macro/function. + **(i (list Pid ...))** Print information about a list of pids. If no list is given then print information about currently running processes in the system. +**(i x y z)** + +Print information about the about #Pid<x.y.z> + **(l Module ...)** Load modules. @@ -122,7 +126,7 @@ **(reset-environment)** Resets the environment to its initial state. This will clear all -variables, functions an macros that have been set. +variables, functions and macros that have been set. **(run File)** @@ -176,7 +180,7 @@ **``*``, ``**``, ``***``** -The values of the previous 3 expressions. +The values of the previous three expressions. **``-``** @@ -221,8 +225,9 @@ Flags that LFE recognizes include the following: +* ``-nobanner`` - starts LFE without showing the banner * ``-h`` or ``--help`` - provides command line usage help -* ``-e`` or ``-eval`` - evaluates a given sexpr +* ``-e`` or ``-eval`` - evaluates a given sexpr in a string * ``-prompt`` - users may supply a value here to override the default ``lfe>`` prompt; note that ``-prompt classic`` will set the prompt to the original ``>`` and ``-prompt`` with no @@ -233,6 +238,17 @@ prompt value containing the string ``~node`` (which will be substituted with the actual name of the node). +There can be multiple string expressions to be evaluated; each one +must be prefixed with an ``-e`` or ``-eval``. String expressions are +run in the LFE repl so shell commands and functions are allowed. They +are all run in the same invocation of the repl so: + +``` +$ lfe -e "(set aaa 42)" -e "(set bbb 84)" -e "(pp (tuple aaa bbb))" +#(42 84) +``` + +If there are string expressions then the LFE repl will ``not`` be run. # RUNNING LFE SHELL SCRIPTS @@ -253,10 +269,16 @@ **script-args** -A list of the arguments to the script as strings. If -no arguments have been given then this will be an -empty list. +A list of the arguments to the script as strings. If no arguments have +been given then this will be an empty list. + +Note that if there are any string expressions to be evaluated then +these must come before the name of the script file and its +arguments. These expressions will be evaluated before the script and +the script will use the environment from the string expressions. +It is possible to run both string expressions and an LFE shell script +and they are then run in the same LFE repl. # SEE ALSO
View file
_service:tar_scm:lfe-1.3.tar.gz/doc/src/lfe_clj.3.md -> _service:tar_scm:lfe-2.1.1.tar.gz/doc/src/lfe_clj.3.md
Changed
@@ -10,7 +10,7 @@ # SYNOPSIS -This module provides Clojure-inpired functions and macros for use in LFE. +This module provides Clojure-inspired functions and macros for use in LFE. # EXPORTS @@ -593,7 +593,7 @@ Return a nullary function that returns a cons cell with `start` as the head and a nullary function, `(next func (funcall func start step) step)` as the tail. The result can be treated as a (possibly infinite) lazy list, which only -computes subseqeuent values as needed. +computes subsequent values as needed. **(lazy-seq seq)** @@ -653,7 +653,7 @@ Return a list of lists of `n` items each, at offsets `step` apart. Use the elements of `pad` as necessary to complete the last partition up to `n` -elements. In case there are not enough padding elements, return a parition with +elements. In case there are not enough padding elements, return a partition with less than `n` items. **(partition-all n lst)**
View file
_service:tar_scm:lfe-1.3.tar.gz/doc/src/lfe_comp.3.md -> _service:tar_scm:lfe-2.1.1.tar.gz/doc/src/lfe_comp.3.md
Changed
@@ -56,6 +56,10 @@ linted LFE code in the files <Module>.lint. No object files are produced. Mainly useful for debugging and interest. +* ``to_erlang``, ``to-erlang`` - Print a listing of the Erlang AST in + the file <Module>.erl. No object files are produced. Mainly useful + for debugging and interest. + * ``to_core0``, ``to-core0``, ``to_core``, ``to-core`` - Print a listing of the Core Erlang code before/after being optimised in the files <Module>.core. No object files are produced. Mainly useful for debugging @@ -123,7 +127,7 @@ Compile the forms as an LFE module returning a binary. This function takes the same options as ``lfe_comp:file/1/2``. When generating Errors and Warnings the "line number" is the index -of the form in which the error occured. +of the form in which the error occurred. **format_error(Error) -> Chars**
View file
_service:tar_scm:lfe-2.1.1.tar.gz/doc/src/lfe_docs.3.md
Added
@@ -0,0 +1,33 @@ +% lfe_docs(3) +% Robert Virding +% 2016 + + +# NAME + +lfe_docs - Lisp Flavoured Erlang (LFE) documentation handling. + + +# SYNOPSIS + +This module provides functions to parse docstrings in LFE module +sources in EEP48 format. + +# EXPORTS + +**make_chunk(Mod, CompilerInfo) -> {ok,DocsChunk}** + +Parse a module's docstrings and return a documentation chunk. + +**make_docs_info(Mod, CompilerInfo) -> {ok,DocsInfo}** + +Parse a module's docstrings and return the documentation info. + +**get_module_docs(Module | Binary) -> {ok,DocsInfo} | {error,Error}** + +Extract the documentation from a module documentation chunk and return +it in the documentation format of the current Erlang version. + +# SEE ALSO + +**lfe_comp(3)**, **lfe_macro(3)**
View file
_service:tar_scm:lfe-1.3.tar.gz/doc/src/lfe_guide.7.md -> _service:tar_scm:lfe-2.1.1.tar.gz/doc/src/lfe_guide.7.md
Changed
@@ -1,15 +1,15 @@ % lfe_guide(7) % Robert Virding -% 2008-2016 +% 2008-2020 # NAME lfe_guide - Lisp Flavoured Erlang User Guide -# SYNPOSIS +# SYNOPSIS -Note: {{ ... }} is use to denote optional syntax. +Note: {{ ... }} is used to denote optional syntax. # LITERALS AND SPECIAL SYNTACTIC RULES @@ -35,7 +35,7 @@ * Binary notation (alternative form): ``` - #*0 #b*10101 #*-1100 + #*0 #*10101 #*-1100 ``` * Octal notation: @@ -53,7 +53,7 @@ * Hexadecimal notation: ``` - #xc0ffe 0x-01 + #xc0ffe #x-01 ``` * Notation with explicit base (up to 36): @@ -100,7 +100,7 @@ 1.0 +1.0 -1.0 1.0e10 1.111e-10 ``` -The one thing to watch out for is that you cannot omit the the part +The one thing to watch out for is that you cannot omit the part before or after the decimal point if it is zero. E.g. the following are not valid forms: ``100.`` or ``.125``. @@ -125,7 +125,7 @@ be convenient when writing Unicode letters not easily typeable or viewable with regular fonts. E.g. ``"Cat: \\x1f639;"`` might be easier to type (and view on output devices without a Unicode font) then typing the -actual unicode letter. +actual Unicode letter. ### Binary Strings @@ -226,7 +226,7 @@ digits don't make a number a symbol when using the explicit number base notation, e.g. ``#b10foo`` gives an error). -<!-- +<!-- Symbol names can contain a surprising breadth or characters: ``` @@ -296,12 +296,16 @@ (tset tuple index val) (binary seg ... ) (map key val ...) -(map-get m k) (map-set m k v ...) (map-update m k v ...) +(map-size map) (msiz m) +(map-get map key) (mref m k) +(map-set map key val ...) (mset m k v ...) +(map-update map key val ...) (mupd m k v ...) +(map-remove map key ...) (mrem m k k ...) (lambda (arg ...) ...) (match-lambda ((arg ... ) {{(when e ...)}} ...) - Matches clauses ... ) -(function func-name arity) - Function references +(function func-name arity) - Function reference (function mod-name func-name arity) (let ((pat {{(when e ...)}} e) ...) @@ -330,19 +334,37 @@ {{(case ((pat {{(when e ...)}} ... ) ... ))}} {{(catch - (((tuple type value ignore) {{(when e ...)}} - - Must be tuple of length 3! + ((tuple type value stacktrace)|_ {{(when e ...)}} + - Must be tuple of length 3 or just _! ... ) ... )}} {{(after ... )}}) (funcall func arg ... ) -(call mod func arg ... ) - Call to Mod:Func(Arg, ... ) +(call mod func arg ... ) - Call to Mod:Func(Arg, ... ) + +(define-record name fields) +(record name field val ...) +(is-record record name) +(record-index name field) +(record-field record name field) +(record-update record name field val ...) + +(define-struct fields) +(struct field val ...) +(is-struct struct) +(is-struct struct name) +(struct-field struct name field) +(struct-update struct name field val ...) (define-module name meta-data attributes) (extend-module meta-data attributes) (define-function name meta-data lambda|match-lambda) (define-macro name meta-data lambda|match-lambda) + +(define-type type definition) +(define-opaque-type type definition) +(define-function-spec func spec) ``` ## Basic macro forms @@ -354,8 +376,9 @@ (call 'mod 'func arg ... ) (? {{timeout {{default}} }}) (++ ... ) -(list* ...) -(let* (...) ... ) +(-- ... ) +(list* ... ) +(let* (... ) ... ) (flet ((name (arg ...) {{doc-string}} ...) ...) ...) @@ -363,18 +386,21 @@ (fletrec ((name (arg ...) {{doc-string}} ...) ...) ...) -(cond ... - {{(?= pat expr)}} - ... ) +(cond (test body ...) + ... + ((?= pat expr) ...) + ... + (else ...)) (andalso ... ) (orelse ... ) (fun func arity) (fun mod func arity) -(lc (qual ...) ...) -(list-comp (qual ...) ...) -(bc (qual ...) ...) -(binary-comp (qual ...) ...) -(match-spec ...) +(lc (qual ...) expr) +(list-comp (qual ...) expr) +(bc (qual ...) bitstringexpr) +(binary-comp (qual ...) bitstringexpr) +(ets-ms ...) +(trace-ms ...) ``` ## Common Lisp inspired macros @@ -404,20 +430,7 @@ (prog2 ...) (defmodule name ...) (defrecord name ...) -``` - -## Older Scheme inspired macros - -``` -(define (name arg ...) ...) -(define name lambda|match-lambda) -(define-syntax name - (syntax-rules (pat exp) ...)|(macro (pat body) ...)) -(let-syntax ((name ...) - ...) - ...) -(begin ...) -(define-record name ...) +(defstruct ...) ``` # Patterns @@ -452,7 +465,7 @@ # Guards Wherever a pattern occurs (in let, case, receive, lc, etc.) it can be -followed by an optional guard which has the form (when test ...). +followed by an optional guard which has the form ``(when test ...)``. Guard tests are the same as in vanilla Erlang and can contain the following guard expressions: @@ -465,9 +478,16 @@ (tuple gexpr ...) (tref gexpr gexpr)
View file
_service:tar_scm:lfe-1.3.tar.gz/doc/src/lfe_io.3.md -> _service:tar_scm:lfe-2.1.1.tar.gz/doc/src/lfe_io.3.md
Changed
@@ -1,6 +1,6 @@ % lfe_io(3) % Robert Virding -% 2008-2016 +% 2008-2019 # NAME @@ -35,29 +35,34 @@ # EXPORTS -**read(IoDevice, Prompt) -> {ok,Sexpr} | {error,ErrorInfo}** +**read(IoDevice, Prompt) -> {ok,Sexpr} | {error,ErrorInfo} | eof** -Read an s-expr from the standard input (IoDevice) with a prompt -(Prompt). Note that this is not line-oriented in that it stops as soon +Read an s-expr from the standard input (``IoDevice``) with a prompt +(``Prompt``). Note that this is not line-oriented in that it stops as soon as it has consumed enough characters. -**read_line(IoDevice, Prompt) -> {ok,Sexpr} | {error,ErrorInfo}** +**read_line(IoDevice, Prompt) -> {ok,Sexpr} | {error,ErrorInfo} | eof** -Read an s-expr from the standard input (IoDevice) with a prompt -(Prompt). Note that this is line-oriented in that it reads whole lines +Read an s-expr from the standard input (``IoDevice``) with a prompt +(``Prompt``). Note that this is line-oriented in that it reads whole lines discarding left-over characters in the last line. **read_string(String) -> {ok,Sexpr} | {error,ErrorInfo}** -Read an s-expr from String. +Read an s-expr from ``String``. Note that this only reads from ``String`` +discarding left-over characters at the end of the string. **print(IoDevice, Sexpr) -> ok** -Print the s-expr Sexpr to the standard output (IoDevice). +Print the s-expr ``Sexpr`` to the standard output (``IoDevice``). **print1(Sexpr) -> DeepCharList** -Return the list of characters which represent the s-expr Sexpr. +Return the list of characters which represent the s-expr ``Sexpr``. + +**prettyprint(IoDevice, Sexpr) -> ok** + +Pretty print the s-expr ``Sexpr`` to the standard output (``IoDevice``). **prettyprint1(Sexpr) -> DeepCharList** @@ -67,9 +72,9 @@ **prettyprint1(Sexpr, Depth, Indentation, LineLength) -> DeepCharList** -Return the lost of characters which represents the -prettyprinted s-expr ``Sexpr``. Assume we start at indentation -Indentation or 0. +Return the list of characters which represents the prettyprinted +s-expr ``Sexpr``. Default values for ``Depth`` is 30, ``Indentation`` +is 0 and ``LineLength`` is 80. **format(IoDevice, Format, Args) -> ok** @@ -96,7 +101,7 @@ **read_file(FileName) -> {ok,Sexpr} | {error,ErrorInfo}** -Read the file Filename returning a list of s-exprs (as it +Read the file ``Filename`` returning a list of s-exprs (as it should be). **parse_file(FileName) -> {ok,FileSexpr} | {error,ErrorInfo}** @@ -107,7 +112,7 @@ FileSexpr = filesexpr() ``` -Read the file Filename returning a list of pairs containing +Read the file ``Filename`` returning a list of pairs containing s-expr and line number of the start of the s-expr. **scan_sexpr(Cont, Chars ,Line) -> {done,Ret,RestChars}|{more,Cont1}**
View file
_service:tar_scm:lfe-1.3.tar.gz/doc/src/lfe_macro.3.md -> _service:tar_scm:lfe-2.1.1.tar.gz/doc/src/lfe_macro.3.md
Changed
@@ -1,6 +1,6 @@ % lfe_macro(3) % Robert Virding -% 2008-2016 +% 2008-2020 # NAME @@ -32,28 +32,30 @@ This is an macro and evaluation environment as created by ``lfe_lib:new_env()``. +**mac_state()** -# EXPORTS - -**expand_forms(FileSexpr, Env) -> ExpRet** +This is the internal state used by the macro expander. -where +# EXPORTS -``` - FileSexpr = filesexpr() - Env = env() - ExpRet = {yes,FileSexpr,Env,Warnings} | {error,Errors,Warnings} -``` +**expand_expr(Sexpr, Env) -> {yes,Exp} | no.** -**macro_forms(FileSexpr, Env) -> {FileSexpr,Env}.** +**expand_expr_1(Sexpr, Env) -> {yes,Exp} | no.** where ``` -FileSexpr = filesexpr() +Sexpr = Exp = sexpr() Env = env() ``` +Test if the top s-expression here is a macro call, if so +expand it and return {yes,Expansion}, if not then return no. +``expand_expr/2`` will expand the top s-expression as much as +possible while ``expand_expr_1/2`` will only try it once. These +functions use the macro definitions in the environment and the +standard pre-defined macros. + **expand_expr_all(Sexpr, Env) -> Sexpr.** where @@ -67,23 +69,55 @@ or just the default macros. Note that any eventual new macro definitions will be lost. -**expand_expr(Sexpr, Env) -> {yes,Exp} | no.** +**expand_form_init(Deep, Keep) -> MacState** -**expand_expr_1(Sexpr, Env) -> {yes,Exp} | no.** +where + +``` + Deep = boolean() + Keep = boolean() + MacState = mac_state() +``` + +Create an internal macro state. ``Deep`` determines whether the form +is to be expanded internally at depth and ``Keep`` whether macro +definition forms are to be kept. + +**expand_fileforms(FileForm, Env, Deep, Keep) -> ExpRet** + +**expand_fileforms(FileForm, Env, MacState) -> ExpRet** where ``` -Sexpr = Exp = sexpr() -Env = env() + FileForm = filesexpr() + Env = env() + Deep = boolean() + Keep = boolean() + MacState = mac_state() + ExpRet = {yes,FileSexpr,Env,Warnings} | + {error,Errors,Warnings} ``` -Test if the top s-expression here is a macro call, if so -expand it and return {yes,Expansion}, if not then return no. -``expand_expr/2`` will expand the top s-expression as much as -possible while ``expand_expr_1/2`` will only try it once. These -functions use the macro definitions in the environment and the -standard pre-defined macros. +expand a sequence of file forms. + +**expand_form(Form, Line, Env, MacState) -> RetState** + +**expand_fileform(FileForm, Env, MacState) -> RetState** + +where + +``` + Form = sexpr() + FileForm = filesexpr() + Line = integer() + Env = env() + MacState = mac_state() + RetState = {ok,Form,Env,Macstate} | + {error,Errors,Warnings,MacState} +``` + +Expand a file form using the environment and macro state. # SEE ALSO
View file
_service:tar_scm:lfe-1.3.tar.gz/doc/src/lfe_types.7.md -> _service:tar_scm:lfe-2.1.1.tar.gz/doc/src/lfe_types.7.md
Changed
@@ -1,6 +1,6 @@ % lfe_types(7) % Robert Virding -% 2016 +% 2021 # NAME @@ -27,9 +27,11 @@ | `(lambda () <type>)` | `fun(() -> <type>)` | | `(lambda (<tlist>) <type>)` | `fun((<tlist>) -> <type>)` | | `(map)` | `map()` | - | `(map <pairlist>)` | `#{<pairlist>}` | + | `#M()` | `#{}` | + | `#M(<key> <value> ...)` | `#{<pairlist>}` | | `(tuple)` | `tuple()` | - | `(tuple <tlist>)` | `{<tlist>}` | + | `#()` | `{}` | + | `#(<tlist>)` | `{<tlist>}` | | `(UNION <tlist>)` | `<type> | <type>` | Apart from the predefined types in the Erlang type system we also have @@ -37,6 +39,10 @@ `call`, `lambda` and `range`. The usage of `bitstring`, `tuple` and `map` have also been extended. +Note that the type `#M()` is the empty map and the type `#()` is the +empty tuple. We can still use the older `(map <key valuelist>)` and +`(tuple <tlist>)` formats when declaring types for maps and tuples. + The general form of bitstrings is `(bitstring m n)` which denotes a bitstring which starts with `m` bits and continues with segments of `n` bits. `(binary)` is a short form for a sequence of bytes while @@ -65,7 +71,7 @@ ## Type Information in Record Declarations -**(defrecord rec (field1 default1 type1) (field2 default2) field3)** +**(defrecord rec (field1 default1 type1) (field2 default2) (field3))** Fields with type annotations *MUST* give a default value and fields without type annotations get the default type `(any)`. @@ -119,3 +125,18 @@ Note we are using the alternate list form with ` ` instead of parentheses to make it easier to see the function arguments. + +# Types and function specifications in the module definition + + +Types can also be defined in the module declaration, for example: + +``` +(defmodule this-module + ... + (type ((foo-type) (tuple 'foo (integer) (list))) + ((bar-type) (tuple 'bar (integer) (list)))) + (spec ((foo 1) ((integer) (foo-type))) + ((id 1) (x x ((x (tuple)))))) + ...) +```
View file
_service:tar_scm:lfe-1.3.tar.gz/doc/src/lfescript.1.md -> _service:tar_scm:lfe-2.1.1.tar.gz/doc/src/lfescript.1.md
Changed
@@ -80,11 +80,11 @@ Emacs which causes it to enter LFE mode when editing the script file. -The rest of the file contains LFE source code. It must always -the function ``main/1``. When the script is run this function will -be called with a list of strings representing the arguments -with which the script was called. It is possible to define, -include and use macros in the source code. +The rest of the file contains LFE source code. It must always contain +the function ``main/1``. When the script is run this function will be +called with a list of strings representing the arguments with which +the script was called. It is possible to define, include and use +macros in the source code. The source code is checked and warnings and errors will be printed. If there are errors the script will not run and it
View file
_service:tar_scm:lfe-1.3.tar.gz/doc/src/version_history.md -> _service:tar_scm:lfe-2.1.1.tar.gz/doc/src/version_history.md
Changed
@@ -117,7 +117,7 @@ Added ``(export all)`` attribute to module definition. Added new records which allow giving default values as in vanilla Erlang. -Records are still compatible with vanilla Erlang but now more pratical +Records are still compatible with vanilla Erlang but now more practical to use. NOTE this change is not backwards compatible as syntax for ``(make- ...)`` and ``(match- ...)`` have changed. Also added general multiple ``(set- ...)`` macro. @@ -126,13 +126,13 @@ functions to be defined when compiling the forms. These are useful for more complex macros. -Better and more documention. The documentation is still normal text +Better and more documentation. The documentation is still normal text files as Edoc and are not in agreement on how things should work. ## v0.3 This is the first version with the modified internal core forms and -macro intefaces for the new CL-inspired style and the older Scheme-inspired +macro interfaces for the new CL-inspired style and the older Scheme-inspired style. Two new modules have been added: @@ -148,7 +148,7 @@ ``-pa`` to find modules if necessary. ``lfe_gen`` is a trial interface for using LFE for dynamic code -generation. LFE is much easier to generate as an Erkang list than +generation. LFE is much easier to generate as an Erlang list than Erlang forms. This module helps with defining and compiling a module. Note, that while it works, this module is very experimental and may change. @@ -161,7 +161,7 @@ keep variables and functions separate and while Core Erlang tries to hide this fact it does not fully succeed. In fact, it is actually impossible to do this given Erlang's property of being able to have -many functions of the same name but with different arites. +many functions of the same name but with different arities. While this is not as elegant and forces the use of funcall to call functions bound to variables it works better. @@ -187,13 +187,13 @@ ```cl (tuple 'ok a b) - ; this is eqivalent to {ok,A,B} + ; this is equivalent to {ok,A,B} #('ok a b) - ; this is eqivalent to {quote,ok,a,b} + ; this is equivalent to {quote,ok,a,b} (binary (f float (size 32)) (rest binary)) - ; this is eqivalent to <<F:32/float,Rest:binary>> + ; this is equivalent to <<F:32/float,Rest:binary>> ``` @@ -213,7 +213,7 @@ It is not yet possible to define functions/macros in the shell but that should use soon be possible. You should also then be able to do -regurgítate which would write all the definitions out to a file. +regurgitate which would write all the definitions out to a file. Running a shell other than the standard erlang one is a bit difficult so I have included a patched version of user_drv.erl from @@ -237,4 +237,3 @@ There is now a lisp prettyprinter in ``lfe_io``. Unfortunately the io functions in ``lfe_io`` are not always obviously named from a lisp viewpoint. -
View file
_service:tar_scm:lfe-1.3.tar.gz/doc/user_guide.txt -> _service:tar_scm:lfe-2.1.1.tar.gz/doc/user_guide.txt
Changed
@@ -3,10 +3,10 @@ NAME - lfe_guide - Lisp Flavoured Erlang User Guide + lfe_guide ‐ Lisp Flavoured Erlang User Guide -SYNPOSIS - Note: {{ ... }} is use to denote optional syntax. +SYNOPSIS + Note: {{ ... }} is used to denote optional syntax. LITERALS AND SPECIAL SYNTACTIC RULES Integers @@ -14,27 +14,27 @@ · Regular decimal notation: - 1234 -123 0 + 1234 ‐123 0 · Binary notation: - #b0 #b10101 #b-1100 + #b0 #b10101 #b‐1100 · Binary notation (alternative form): - #*0 #b*10101 #*-1100 + #*0 #*10101 #*‐1100 · Octal notation: - #o377 #o-111 + #o377 #o‐111 · Explicitly decimal notation: - #d1234 #d-123 #d0 + #d1234 #d‐123 #d0 · Hexadecimal notation: - #xc0ffe 0x-01 + #xc0ffe #x‐01 · Notation with explicit base (up to 36): @@ -50,58 +50,58 @@ #\x1f42d; In all these forms, the case of the indicating letter is not signifi‐ - cant, i.e. #b1010 and #B1010 are identical as are #16rf00 and #16Rf00. + cant, i.e. #b1010 and #B1010 are identical as are #16rf00 and #16Rf00. - Similarly, the case is not significant for digits beyond 9 (i.e. 'a', - 'b', 'c', ... for number bases larger than 10), e.g. #xabcd is the - same as #xABCD and can even be mixed in the same number, e.g. #36rHel‐ - loWorld is valid and the same number as #36Rhelloworld and #36rHEL‐ + Similarly, the case is not significant for digits beyond 9 (i.e. ‘a’, + ‘b’, ‘c’, ... for number bases larger than 10), e.g. #xabcd is the + same as #xABCD and can even be mixed in the same number, e.g. #36rHel‐ + loWorld is valid and the same number as #36Rhelloworld and #36rHEL‐ LOWORLD. The character notation using hexadecimal code representation (#\x....;) - is basically the same thing as the regular hexadecimal notation #x... - except that it conveys to the reader that a character is intended and - that it does a sanity check on the value (e.g. negative numbers and + is basically the same thing as the regular hexadecimal notation #x... + except that it conveys to the reader that a character is intended and + that it does a sanity check on the value (e.g. negative numbers and value outside the Unicode range are not permitted). Floating point numbers - There is only one type of floating point numbers and the literals are - written in the usual way, e.g. these are all valid floating point num‐ + There is only one type of floating point numbers and the literals are + written in the usual way, e.g. these are all valid floating point num‐ bers: - 1.0 +1.0 -1.0 1.0e10 1.111e-10 + 1.0 +1.0 ‐1.0 1.0e10 1.111e‐10 - The one thing to watch out for is that you cannot omit the the part be‐ - fore or after the decimal point if it is zero. E.g. the following are - not valid forms: 100. or .125. + The one thing to watch out for is that you cannot omit the part before + or after the decimal point if it is zero. E.g. the following are not + valid forms: 100. or .125. Strings There are two forms of strings: list strings and binary strings. List Strings - List strings are just lists of integers (where the values have to be + List strings are just lists of integers (where the values have to be from a certain set of numbers that are considered valid characters) but - they have their own syntax for literals (which will also be used for - integer lists as an output representation if the list contents looks - like it is meant to be a string): "any text between double quotes where - " and other special characters like \n can be escaped". - - As a special case you can also write out the character number in the - form \xHHH; (where "HHH" is an integer in hexadecimal notation), e.g. - "\x61;\x62;\x63;" is a complicated way of writing "abc". This can be - convenient when writing Unicode letters not easily typeable or viewable - with regular fonts. E.g. "Cat: \\x1f639;" might be easier to type - (and view on output devices without a Unicode font) then typing the ac‐ - tual unicode letter. + they have their own syntax for literals (which will also be used for + integer lists as an output representation if the list contents looks + like it is meant to be a string): “any text between double quotes where + " and other special characters like \n can be escaped”. + + As a special case you can also write out the character number in the + form \xHHH; (where “HHH” is an integer in hexadecimal notation), + e.g. "\x61;\x62;\x63;" is a complicated way of writing "abc". This can + be convenient when writing Unicode letters not easily typeable or view‐ + able with regular fonts. E.g. "Cat: \\x1f639;" might be easier to + type (and view on output devices without a Unicode font) then typing + the actual Unicode letter. Binary Strings Binary strings are just like list strings but they are represented dif‐ - ferently in the virtual machine. The simple syntax is #"...", e.g. - #"This is a binary string \n with some \"escaped\" and quot‐ - ed (\\x1f639;) characters" + ferently in the virtual machine. The simple syntax is #"...", e.g. + #"This is a binary string \n with some \"escaped\" and quoted + (\\x1f639;) characters" You can also use the general format for creating binaries (#B(...), de‐ - scribed below), e.g. #B("a"), #"a", and #B(97) are all the same binary + scribed below), e.g. #B("a"), #"a", and #B(97) are all the same binary string. Character Escaping @@ -109,7 +109,7 @@ escaped name: | Escaped name | Character | - |--------------+-----------------| + |‐‐‐‐‐‐‐‐‐‐‐‐‐‐+‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐| | \b | Backspace | | \t | Tab | | \n | Newline | @@ -120,21 +120,21 @@ | \s | Space | | \d | Delete | - Alternatively you can also use the hexadecimal character encoding, e.g. - "a\nb" and "a\x0a;b" are the same string. + Alternatively you can also use the hexadecimal character encoding, + e.g. "a\nb" and "a\x0a;b" are the same string. Binaries We have already seen binary strings, but the #B(...) syntax can be used - to create binaries with any contents. Unless the contents is a simple + to create binaries with any contents. Unless the contents is a simple integer you need to annotate it with a type and/or size. Example invocations are that show the various annotations: > #B(42 (42 (size 16)) (42 (size 32))) #B(42 0 42 0 0 0 42) - > #B(-42 111 (-42 (size 16)) 111 (-42 (size 32))) - #B(-42 111 (-42 (size 16)) 111 (-42 (size 32))) - > #B((42 (size 32) big-endian) (42 (size 32) little-endian)) + > #B(‐42 111 (‐42 (size 16)) 111 (‐42 (size 32))) + #B(‐42 111 (‐42 (size 16)) 111 (‐42 (size 32))) + > #B((42 (size 32) big‐endian) (42 (size 32) little‐endian)) #B(0 0 0 42 42 0 0 0) > #B((1.23 float) (1.23 (size 32) float) (1.23 (size 64) float)) #B(63 243 174 20 122 225 71 174 63 157 112 164 63 243 174 20 @@ -142,13 +142,13 @@ > #B((#"a" binary) (#"b" binary)) #"ab" - Learn more about "segments" of binary data e.g. in "Learn You Some Er‐ - lang (http://learnyousomeerlang.com/starting-out-for-real#bit-syntax)" - <http://learnyousomeerlang.com/starting-out-for-real#bit-syntax>. + Learn more about “segments” of binary data e.g. in “Learn You Some Er‐ + lang (http://learnyousomeerlang.com/starting‐out‐for‐real#bit‐syntax)” + <http://learnyousomeerlang.com/starting‐out‐for‐real#bit‐syntax>. Lists - Lists are formed either as ( ... ) or ... where the optional ele‐ - ments of the list are separated by some form or whitespace. For exam‐ + Lists are formed either as ( ... ) or ... where the optional ele‐ + ments of the list are separated by some form or whitespace. For exam‐ ple: () @@ -163,33 +163,33 @@ so valid. Maps - Maps are written as #M(key1 value1 key2 value2 ...) The empty map is + Maps are written as #M(key1 value1 key2 value2 ...) The empty map is
View file
_service:tar_scm:lfe-1.3.tar.gz/emacs/inferior-lfe.el -> _service:tar_scm:lfe-2.1.1.tar.gz/emacs/inferior-lfe.el
Changed
@@ -1,6 +1,6 @@ ;;; inferior-lfe.el --- Inferior Lisp Flavoured Erlang mode -;; Copyright (c) 2012-2013 Robert Virding +;; Copyright (c) 2012-2020 Robert Virding ;; ;; Licensed under the Apache License, Version 2.0 (the "License"); ;; you may not use this file except in compliance with the License. @@ -29,6 +29,7 @@ (set-keymap-parent map lisp-mode-shared-map) (define-key map "\C-x\C-e" 'lfe-eval-last-sexp) (define-key map "\C-c\M-o" 'inferior-lfe-clear-buffer) + (define-key map "\C-j" 'inferior-lfe-newline-and-maybe-indent) map) "Keymap for inferior LFE mode.") @@ -41,15 +42,22 @@ (define-key lfe-mode-map "\C-x\C-e" 'lfe-eval-last-sexp) ; GNU convention (define-key lfe-mode-map "\C-c\C-r" 'lfe-eval-region) (define-key lfe-mode-map "\C-c\C-z" 'switch-to-lfe) +(define-key lfe-mode-map "\C-c\C-k" 'lfe-compile) ; Erlang mode convention ;; (defvar inferior-lfe-program "lfe -pa /Users/rv/erlang/lfe/ebin -env TERM vt100" -(defvar inferior-lfe-program "lfe" - "*Program name for invoking an inferior LFE in Inferior LFE mode.") +(defcustom inferior-lfe-program "lfe" + "*Program name for invoking an inferior LFE in Inferior LFE mode." + :group 'lfe + :type 'string) -(defvar inferior-lfe-program-options '("-pa" "/Users/rv/erlang/lfe/ebin") +(defcustom inferior-lfe-program-options '("-pa" "/Users/rv/erlang/lfe/ebin") "*The options used when activating the LFE shell. -This must be a list of strings.") +This must be a list of strings. +You may add the following command line options: +- \"-nobanner\"." + :group 'lfe + :type '(repeat string)) (defvar inferior-lfe-prompt "^^>*>+ *" "*Regexp to recognise prompts in the Inferior LFE mode.") @@ -64,6 +72,15 @@ "*Input matching this regexp are not saved on the history list. Defaults to a regexp ignoring all inputs of 0, 1, or 2 letters.") +(defvar inferior-lfe-indent-on-Cj nil + "*Defines if on C-j the line is indented.") + +(defvar inferior-lfe-check-if-rebar-project nil + "*Checks if there is a `rebar.config' file within the 4 levels of nested folders. +If yes, then there will be a prompt on starting inferior-lfe +to choose whether to run the lfe process using rebar3, +else lfe will be run as usual.") + ;;;###autoload (defun inferior-lfe-mode () "Major mode for interacting with an inferior LFE process. @@ -96,31 +113,36 @@ (save-excursion (let ((end (point))) (backward-sexp) - (buffer-substring (point) end)))) + (buffer-substring (max (point) (comint-line-beginning-position)) end)))) + +(defun inferior-lfe--is-rebar-project () + "Return the project root directory." + (locate-dominating-file default-directory "rebar.config")) + +(defun inferior-lfe--start-rebar-lfe () + (string= (read-answer "Rebar3 project detected. Start lfe repl using rebar3? " + '(("yes" ?y "use rebar3") + ("no" ?n "use regular lfe"))) + "yes")) ;;;###autoload -(defun inferior-lfe (cmd) +(defun inferior-lfe () "Run an inferior LFE process, input and output via a buffer `*inferior-lfe*'. -If `CMD' is given, use it to start the shell, otherwise: -`inferior-lfe-program' `inferior-lfe-program-options' -env TERM vt100." - ;; (interactive (list (if current-prefix-arg - ;; (read-string "Run LFE: " inferior-lfe-program) - ;; inferior-lfe-program))) - ;; (if (not (comint-check-proc "*inferior-lfe*")) - ;; (let ((cmdlist (split-string cmd))) - ;; (set-buffer (apply (function make-comint) - ;; "inferior-lfe" (car cmdlist) nil (cdr cmdlist))) - ;; (inferior-lfe-mode))) - (interactive (list (if current-prefix-arg - (read-string "Run LFE: ") - ()))) - (let (prog opts) - (if cmd - (setq prog "sh" - opts (list "-i" "-c" cmd)) - (setq prog inferior-lfe-program - opts (append inferior-lfe-program-options - '("-env" "TERM" "vt100")))) +Start the shell `inferior-lfe-program' `inferior-lfe-program-options' -env TERM vt100. +If a rebar project is found you are prompted (see `inferior-lfe-check-if-rebar-project') +and can choose to run lfe using rebar3." + (interactive) + (let ((prog inferior-lfe-program) + (opts (append inferior-lfe-program-options + '("-env" "TERM" "vt100"))) + (rebar-project-root (inferior-lfe--is-rebar-project))) + (when (and inferior-lfe-check-if-rebar-project + rebar-project-root + (inferior-lfe--start-rebar-lfe)) + (setq prog "sh" + opts (list "-i" "-c" (concat "TERM=\"vt100\";" + (format "cd %s" rebar-project-root) + "; rebar3 lfe repl")))) (unless (comint-check-proc "*inferior-lfe*") (set-buffer (apply (function make-comint) "inferior-lfe" prog nil opts)) @@ -128,13 +150,18 @@ (setq inferior-lfe-buffer "*inferior-lfe*") (pop-to-buffer "*inferior-lfe*"))) -;; (apply (function make-comint) -;; "inferior-lfe" "sh" nil -;; (quote ("-i" "-c" ". /Users/rv/.bashrc ; lfe -env TERM vt100"))) - ;;;###autoload (defalias 'run-lfe 'inferior-lfe) +(defun inferior-lfe-newline-and-maybe-indent () + "Sends a newline and indents the line when `inferior-lfe-indent-on-Cj' is true." + (interactive) + (save-restriction + (narrow-to-region comint-last-input-start (point-max)) + (insert "\n") + (when inferior-lfe-indent-on-Cj + (lisp-indent-line)))) + (defun lfe-eval-region (start end &optional and-go) "Send the current region (from `START' to `END') to the inferior LFE process. `AND-GO' means switch to the LFE buffer afterwards." @@ -149,6 +176,14 @@ (interactive "P") (lfe-eval-region (save-excursion (backward-sexp) (point)) (point) and-go)) +(defun lfe-compile () + "Compiles the LFE module in the current buffer using the inferior LFE process." + (interactive) + (let ((file (buffer-file-name))) + (comint-send-string (inferior-lfe-proc) "(c \"") + (comint-send-string (inferior-lfe-proc) file) + (comint-send-string (inferior-lfe-proc) "\")\n"))) + (defun switch-to-lfe (eob-p) "Switch to the inferior Lisp process buffer. When `EOB-P' is given, position cursor at end of buffer."
View file
_service:tar_scm:lfe-1.3.tar.gz/emacs/lfe-indent.el -> _service:tar_scm:lfe-2.1.1.tar.gz/emacs/lfe-indent.el
Changed
@@ -1,6 +1,6 @@ ;;; lfe-indent.el --- Lisp Flavoured Erlang indent mode -;; Copyright (c) 2015 Robert Virding +;; Copyright (c) 2015-2020 Robert Virding ;; ;; Licensed under the Apache License, Version 2.0 (the "License"); ;; you may not use this file except in compliance with the License.
View file
_service:tar_scm:lfe-1.3.tar.gz/emacs/lfe-mode.el -> _service:tar_scm:lfe-2.1.1.tar.gz/emacs/lfe-mode.el
Changed
@@ -1,6 +1,6 @@ ;;; lfe-mode.el --- Lisp Flavoured Erlang mode -;; Copyright (c) 2012-2015 Robert Virding +;; Copyright (c) 2012-2020 Robert Virding ;; ;; Licensed under the Apache License, Version 2.0 (the "License"); ;; you may not use this file except in compliance with the License. @@ -208,6 +208,7 @@ "match-lambda" "progn" "receive" "try" "when" ;; Core macro forms. "andalso" "bc" "binary-comp" "cond" "do" + "dbg-ms" "ets-ms" "table-ms" "trace-ms" "flet" "flet*" "fletrec" "fun" "lc" "list-comp" "let*" "match-spec" "macrolet" "orelse"
View file
_service:tar_scm:lfe-1.3.tar.gz/emacs/lfe-start.el -> _service:tar_scm:lfe-2.1.1.tar.gz/emacs/lfe-start.el
Changed
@@ -1,6 +1,6 @@ ;;; lfe-start.el --- Initialise the LFE mode package -;; Copyright (c) 2012-2013 Robert Virding +;; Copyright (c) 2012-2020 Robert Virding ;; ;; Licensed under the Apache License, Version 2.0 (the "License"); ;; you may not use this file except in compliance with the License.
View file
_service:tar_scm:lfe-1.3.tar.gz/examples/church.lfe -> _service:tar_scm:lfe-2.1.1.tar.gz/examples/church.lfe
Changed
@@ -1,4 +1,4 @@ -;; Copyright (c) 2013 Duncan McGreggor <oubiwann@cogitat.io> +;; Copyright (c) 2013-2020 Duncan McGreggor <oubiwann@gmail.com> ;; ;; Licensed under the Apache License, Version 2.0 (the "License"); ;; you may not use this file except in compliance with the License. @@ -21,19 +21,21 @@ ;; ;; Here is some example usage: ;; -;; > (slurp '"church.lfe") +;; $ ./bin/lfe +;; +;; lfe> (slurp "examples/church.lfe") ;; #(ok church) -;; > (zero) +;; lfe> (zero) ;; #Fun<lfe_eval.10.53503600> -;; > (church->int1 (zero)) +;; lfe> (church->int1 (zero)) ;; 0 -;; > (church->int1 (three)) +;; lfe> (church->int1 (three)) ;; 3 -;; > (church->int1 (five)) +;; lfe> (church->int1 (five)) ;; 5 -;; > (church->int2 #'five/0) +;; lfe> (church->int2 #'five/0) ;; 5 -;; > (church->int2 (lambda () (get-church 25))) +;; lfe> (church->int2 (lambda () (get-church 25))) ;; 25 (defmodule church
View file
_service:tar_scm:lfe-1.3.tar.gz/examples/core-macros.lfe -> _service:tar_scm:lfe-2.1.1.tar.gz/examples/core-macros.lfe
Changed
@@ -1,4 +1,4 @@ -;; Copyright (c) 2008-2015 Robert Virding +;; Copyright (c) 2008-2020 Robert Virding ;; ;; Licensed under the Apache License, Version 2.0 (the "License"); ;; you may not use this file except in compliance with the License. @@ -25,6 +25,15 @@ ;; recursive more syntax pattern based expansion. This to show ;; different styles of doing the same thing. +;; Here is some example usage: +;; +;; $ ./bin/lfe +;; +;; lfe> (include-file "examples/core-macros.lfe") +;; () +;; lfe> (:: init get_status) +;; #(started started) + (defmacro caar (x) `(car (car ,x))) (defmacro cadr (x) `(car (cdr ,x))) (defmacro cdar (x) `(cdr (car ,x))) @@ -96,7 +105,7 @@ (() `'false))) ;; This version of backquote is almost an exact copy of a quasiquote -;; expander for Scheme by André van Tonder. It is very compact and +;; expander for Scheme by André van Tonder. It is very compact and ;; with some cons/append optimisations we have added produces quite ;; reasonable code.
View file
_service:tar_scm:lfe-1.3.tar.gz/examples/ets_demo.lfe -> _service:tar_scm:lfe-2.1.1.tar.gz/examples/ets_demo.lfe
Changed
@@ -1,4 +1,4 @@ -;; Copyright (c) 2008-2013 Robert Virding +;; Copyright (c) 2008-2020 Robert Virding ;; ;; Licensed under the Apache License, Version 2.0 (the "License"); ;; you may not use this file except in compliance with the License. @@ -21,15 +21,34 @@ ;; with ets:match/match_object and match specifications with ;; ets:select. +;; Here is some example usage: +;; +;; $ ./bin/lfe +;; +;; lfe> (c "examples/ets_demo.lfe") +;; (#(module ets_demo)) +;; lfe> (set db (ets_demo:new)) +;; #Ref<0.2772763705.1333133315.72774> +;; lfe> (ets_demo:by_place db 'london) +;; #(((paul driver) (fred waiter) (john painter) (bert waiter)) +;; (#(person paul london driver) +;; #(person fred london waiter) +;; #(person john london painter) +;; #(person bert london waiter))) + (defmodule ets_demo - (export (new 0) (by_place 2) (by_place_ms 2) (not_painter 2))) + (export + (new 0) + (by_place 2) + (by_place_ms 2) + (not_painter 2))) ;; Define a simple person record to work on. (defrecord person name place job) ;; Create an initialse the ets table. (defun new () - (let ((db (: ets new 'ets_demo '(#(keypos 2) set)))) + (let ((db (ets:new 'ets_demo '(#(keypos 2) set)))) (let ((people '( ;; First some people in London. #(fred london waiter) @@ -49,27 +68,27 @@ #(fritz berlin painter) #(kurt berlin driver) #(hans berlin waiter) - #(franz berlin waiter) - ))) - (: lists foreach (match-lambda - ((tuple n p j) - (: ets insert db (make-person name n place p job j)))) + #(franz berlin waiter)))) + (lists:foreach + (match-lambda + ((tuple n p j) + (ets:insert db (make-person name n place p job j)))) people)) - db)) ;Return the table + db)) ;; Return the table ;; Match records by place using match, match_object and the emp-XXXX macro. (defun by_place (db place) - (let ((s1 (: ets match db (emp-person name '$1 place place job '$2))) - (s2 (: ets match_object db (emp-person place place)))) + (let ((s1 (ets:match db (emp-person name '$1 place place job '$2))) + (s2 (ets:match_object db (emp-person place place)))) (tuple s1 s2))) ;; Use match specifications to match records (defun by_place_ms (db place) - (: ets select db (match-spec ((match-person name n place p job j) - (when (=:= place p)) - (list 'p n j))))) + (ets:select db (match-spec ((match-person name n place p job j) + (when (=:= place p)) + (list 'p n j))))) (defun not_painter (db place) - (: ets select db (match-spec ((match-person name n place p job j) - (when (=:= place p) (=/= j 'painter)) - (list 'p n j))))) + (ets:select db (match-spec ((match-person name n place p job j) + (when (=:= place p) (=/= j 'painter)) + (list 'p n j)))))
View file
_service:tar_scm:lfe-1.3.tar.gz/examples/fizzbuzz.lfe -> _service:tar_scm:lfe-2.1.1.tar.gz/examples/fizzbuzz.lfe
Changed
@@ -1,4 +1,4 @@ -;; Copyright (c) 2008-2013 Sean Chalmers +;; Copyright (c) 2008-2020 Sean Chalmers ;; ;; Licensed under the Apache License, Version 2.0 (the "License"); ;; you may not use this file except in compliance with the License. @@ -23,11 +23,28 @@ ;; There are no doubt more interesting or extensible ways of solving FizzBuzz, ;; however I felt this was a good example of using both Pattern Matching and ;; Higher Order Functions (lists:map/2) in a very simplistic way. + +;; Here is some example usage: +;; +;; $ ./bin/lfe +;; +;; lfe> (c "examples/fizzbuzz.lfe") +;; (#(module fizzbuzz)) +;; lfe> (fizzbuzz:buzz 1) +;; (1) +;; lfe> (fizzbuzz:buzz 2) +;; (1 2) +;; lfe> (fizzbuzz:buzz 5) +;; (1 2 "Buzz" 4 "Fizz") +;; lfe> (fizzbuzz:buzz 10) +;; (1 2 "Buzz" 4 "Fizz" "Buzz" 7 8 "Buzz" "Fizz") + (defmodule fizzbuzz - (export (buzz 1) - (buzz1 1) - (buzz2 1) - (buzz3 1))) + (export + (buzz 1) + (buzz1 1) + (buzz2 1) + (buzz3 1))) (defun get-fizz (n) ;; Request a FizzBuzz result for a given number. @@ -46,11 +63,11 @@ (defun buzz (n) ;; This is the basic version, takes an argument ;; and attempts to create result list of results. - (: lists map + (lists:map ;; Wrap our call to 'get-fizz in a lambda (lambda (x) (get-fizz x)) ;; Create a list of numbers from one to n - (: lists seq 1 n))) + (lists:seq 1 n))) (defun buzz1 ;; This version utilises pattern matching and guard to @@ -58,7 +75,7 @@ ;; unwanted arguments. ;; Only run the FizzBuzz solution when we have a positive ;; whole number that is greater than zero - (n (when (and (: erlang is_integer n) + (n (when (and (erlang:is_integer n) (> n 0))) ;; woo! (buzz n))
View file
_service:tar_scm:lfe-1.3.tar.gz/examples/gps1.lfe -> _service:tar_scm:lfe-2.1.1.tar.gz/examples/gps1.lfe
Changed
@@ -1,6 +1,7 @@ ;; -*- Mode: LFE; -*- ;; Code from Paradigms of Artificial Intelligence Programming -;; Copyright (c) 1991 Peter Norvig +;; Copyright (c) 1991 Peter Norvig, Common Lisp version +;; Copyright (c) 2008-2020 Robert Virding ;; File : gps1.lisp ;; Author : Peter Norvig, Robert Virding @@ -12,9 +13,11 @@ ;; ;; Here is some example usage for a successful run: ;; -;; > (slurp '"examples/gps1.lfe") +;; $ ./bin/lfe +;; +;; lfe> (slurp "examples/gps1.lfe") ;; #(ok gps1) -;; > (gps '(son-at-home car-needs-battery have-money have-phone-book) +;; lfe> (gps '(son-at-home car-needs-battery have-money have-phone-book) ;; '(son-at-school) ;; (school-ops)) ;; executing 'look-up-number' @@ -24,11 +27,11 @@ ;; executing 'shop-installs-battery' ;; executing 'drive-son-to-school' ;; solved -;; > +;; lfe> ;; ;; Here is an unsuccessful run: ;; -;; > (gps '(son-at-home car-needs-battery have-money have-phone-book) +;; lfe> (gps '(son-at-home car-needs-battery have-money have-phone-book) ;; '(son-at-school have-money) ;; (school-ops)) ;; executing 'look-up-number' @@ -38,14 +41,16 @@ ;; executing 'shop-installs-battery' ;; executing 'drive-son-to-school' ;; false -;; > +;; lfe> ;; ;; And a trivial run (for Saturdays!): ;; -;; > (gps '(son-at-home) '(son-at-home) (school-ops)) +;; lfe> (gps '(son-at-home) '(son-at-home) (school-ops)) ;; solved ;; +(include-lib "lfe/include/scm.lfe") + ;; Define macros for global variable access. This is a hack and very naughty! (defsyntax defvar (name val (let ((v val)) (put 'name v) v))) @@ -58,10 +63,20 @@ ;; Module definition. (defmodule gps1 - (export (gps 2) (gps 3) (school-ops 0)) - (import (from lists (member 2) (all 2) (any 2)) - ;; Rename lists functions to be more CL like. - (rename lists ((all 2) every) ((any 2) some) ((filter 2) find-all)))) + (export + (gps 2) + (gps 3) + (school-ops 0)) + (import + (from lists + (member 2) + (all 2) + (any 2)) + ;; Rename lists functions to be more CL like. + (rename lists + ((all 2) every) + ((any 2) some) + ((filter 2) find-all)))) ;; An operation. (defrecord op @@ -95,7 +110,7 @@ (defun apply-op (op) (if (every (fun achieve 1) (op-preconds op)) (progn - (: io fwrite '"executing ~p\n" (list (op-action op))) + (io:fwrite "executing ~p\n" (list (op-action op))) (setvar *state* (set-difference (getvar *state*) (op-del-list op))) (setvar *state* (union (getvar *state*) (op-add-list op))) 'true)))
View file
_service:tar_scm:lfe-1.3.tar.gz/examples/guessing-game.lfe -> _service:tar_scm:lfe-2.1.1.tar.gz/examples/guessing-game.lfe
Changed
@@ -1,4 +1,4 @@ -;; Copyright (c) 2013 Duncan McGreggor <oubiwann@cogitat.io> +;; Copyright (c) 2013-2020 Duncan McGreggor <oubiwann@gmail.com> ;; ;; Licensed under the Apache License, Version 2.0 (the "License"); ;; you may not use this file except in compliance with the License. @@ -20,8 +20,9 @@ ;; This file contains a simple demo for guessing a random number, chosen by ;; "the computer". To use, do the following: ;; -;; $ ../bin/lfe -pa ../ebin -;; > (slurp '"examples/guessing-game.lfe") +;; $ ./bin/lfe +;; +;; > (slurp "examples/guessing-game.lfe") ;; #(ok guessing-game) ;; > (main) ;; Guess the number I have chosen, between 1 and 10. @@ -37,23 +38,25 @@ ;; > (defmodule guessing-game - (export (main 0))) + (export + (main 0))) (defun get-player-guess () - (let (((tuple 'ok (list guessed)) (: io fread '"Guess number: " '"~d"))) + (let (((tuple 'ok (list guessed)) (io:fread "Guess number: " "~d"))) guessed)) (defun check-guess (answer guessed) (cond ((== answer guessed) - (: io format '"Well-guessed!!~n")) + (io:format "Well-guessed!!~n") + 'game-over) ((/= answer guessed) - (if (> answer guessed) (: io format '"Your guess is too low.~n")) - (if (< answer guessed) (: io format '"Your guess is too high.~n")) + (if (> answer guessed) (io:format "Your guess is too low.~n")) + (if (< answer guessed) (io:format "Your guess is too high.~n")) (check-guess answer (get-player-guess))))) (defun main () - (: io format '"Guess the number I have chosen, between 1 and 10.~n") + (io:format "Guess the number I have chosen, between 1 and 10.~n") (check-guess - (: random uniform 10) + (random:uniform 10) (get-player-guess)))
View file
_service:tar_scm:lfe-2.1.1.tar.gz/examples/guessing-game2.lfe
Added
@@ -0,0 +1,99 @@ +;; Copyright (c) 2020 Duncan McGreggor <oubiwann@cogitat.io> +;; +;; Licensed under the Apache License, Version 2.0 (the "License"); +;; you may not use this file except in compliance with the License. +;; You may obtain a copy of the License at +;; +;; http://www.apache.org/licenses/LICENSE-2.0 +;; +;; Unless required by applicable law or agreed to in writing, software +;; distributed under the License is distributed on an "AS IS" BASIS, +;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +;; See the License for the specific language governing permissions and +;; limitations under the License. + +;; File : guessing-game2.lfe +;; Author : Duncan McGreggor +;; Purpose : Demonstrating a random-number guessing game (classic BASIC-era +;; demo) using a simple client and server, message-passing, and +;; pattern-matching + +;; This file contains a simple demo for guessing a random number, chosen by +;; "the computer". Outwardly, this example behaves exactly like the first +;; guessing game example. Internally, however, this one differs significantly: +;; +;; 1. It uses a record to track game state +;; 2. It has abstrated a client behaviour and a server behaviour +;; 3. It uses message-passing between these two +;; 4. It uses pattern matching of records in the function heads as well as the +;; receives to perform flow control (instead of the 'cond' and `if` forms) +;; +;; To use, do the following: +;; +;; $ ./bin/lfe +;; +;; > (slurp "examples/guessing-game2.lfe") +;; #(ok guessing-game) +;; lfe> (main) +;; Guess the number I have chosen, between 1 and 10. +;; Guess number: 1 +;; Your guess is too low. +;; Guess number: 10 +;; Your guess is too high. +;; Guess number: 5 +;; Your guess is too low. +;; Guess number: 7 +;; Your guess is too high. +;; Guess number: 6 +;; Well-guessed!! +;; game-over + +(defmodule guessing-game2 + (export + (main 0))) + +(defrecord state + server + client + answer + guess + status) + +(defun guess-server + (((match-state answer a)) + (receive + ((= (match-state client p guess g) game) (when (== g a)) + (! p (set-state-status game 'game-over))) + ((= (match-state client p guess g) game) (when (> g a)) + (! p (set-state-status game 'too-high)) + (guess-server game)) + ((= (match-state client p guess g) game) (when (< g a)) + (! p (set-state-status game 'too-low)) + (guess-server game))))) + +(defun guess-client + (((match-state status 'game-over)) + (io:format "Well-guessed!!~n") + 'game-over) + (((= (match-state status 'started) game)) + (io:format "Guess the number I have chosen, between 1 and 10.~n") + (guess-client (set-state-status game 'running))) + (((= (match-state status 'too-high) game)) + (io:format "Your guess is too high.~n") + (guess-client (set-state-status game 'running))) + (((= (match-state status 'too-low) game)) + (io:format "Your guess is too low.~n") + (guess-client (set-state-status game 'running))) + (((= (match-state server p) game)) + (let ((`#(ok (,g)) (io:fread "Guess number: " "~d"))) + (! p (set-state game client (self) guess g)) + (receive + (game (guess-client game)))))) + +(defun main () + (let* ((a (random:uniform 10)) + (s (make-state answer a + guess 'undefined + status 'started)) + (p (spawn (lambda () (guess-server s))))) + (guess-client (set-state-server s p))))
View file
_service:tar_scm:lfe-1.3.tar.gz/examples/http-async.lfe -> _service:tar_scm:lfe-2.1.1.tar.gz/examples/http-async.lfe
Changed
@@ -1,4 +1,4 @@ -;; Copyright (c) 2013 Duncan McGreggor <oubiwann@cogitat.io> +;; Copyright (c) 2013-2020 Duncan McGreggor <oubiwann@gmail.com> ;; ;; Licensed under the Apache License, Version 2.0 (the "License"); ;; you may not use this file except in compliance with the License. @@ -64,33 +64,35 @@ ;; Here is some example usage from the REPL: ;; -;; > (slurp '"examples/http-async.lfe") +;; $ ./bin/lfe +;; +;; lfe> (slurp "examples/http-async.lfe") ;; #(ok http-async) -;; > (get-pages (list '"http://lfe.github.io/")) +;; lfe> (get-pages (list "http://lfe.io/")) ;; Result: {{"HTTP/1.1",200,"OK"}, ;; {"cache-control","max-age=600"}, ;; {"connection","keep-alive"}, ;; ... ;; ok -;; > +;; lfe> ;; ;; The get-pages function starts the inets service for you. If you would like ;; to call get-page directly (without first having called get-pages), you'll ;; have to start that yourself: ;; -;; > (: inets start) -;; > (get-page '"http://lfe.github.io/") +;; lfe> (inets:start) +;; lfe> (ssl:start) +;; lfe> (get-page "https://lfe.io/") ;; Result: {{"HTTP/1.1",200,"OK"}, ;; {"cache-control","max-age=600"}, ;; {"connection","keep-alive"}, ;; ... ;; ok -;; > +;; lfe> (defmodule http-async (export all)) - (defun parse-args (flag) "Given one or more command-line arguments, extract the passed values. @@ -105,8 +107,8 @@ ) In this example, the value assigned to the arg variable would be a list containing the values my-value-1 and my-value-2." - (let (((tuple 'ok data) (: init get_argument flag))) - (: lists merge data))) + (let (((tuple 'ok data) (init:get_argument flag))) + (lists:merge data))) (defun get-pages () "With no argument, assume 'url parameter was passed via command line." @@ -115,8 +117,9 @@ (defun get-pages (urls) "Start inets and make (potentially many) HTTP requests." - (: inets start) - (: plists map + (inets:start) + (ssl:start) + (plists:map (lambda (x) (get-page x)) urls)) @@ -127,9 +130,9 @@ (request-data (tuple url headers)) (http-options ()) (request-options (list (tuple 'sync 'false)))) - (: httpc request method request-data http-options request-options) + (httpc:request method request-data http-options request-options) (receive ((tuple 'http (tuple request-id (tuple 'error reason))) - (: io format '"Error: ~p~n" (list reason))) + (io:format "Error: ~p~n" (list reason))) ((tuple 'http (tuple request-id result)) - (: io format '"Result: ~p~n" (list result)))))) + (io:format "Result: ~p~n" (list result))))))
View file
_service:tar_scm:lfe-1.3.tar.gz/examples/http-sync.lfe -> _service:tar_scm:lfe-2.1.1.tar.gz/examples/http-sync.lfe
Changed
@@ -1,4 +1,4 @@ -;; Copyright (c) 2013 Duncan McGreggor <oubiwann@cogitat.io> +;; Copyright (c) 2013-2020 Duncan McGreggor <oubiwann@gmail.com> ;; ;; Licensed under the Apache License, Version 2.0 (the "License"); ;; you may not use this file except in compliance with the License. @@ -49,27 +49,30 @@ ;; Here is some example usage from the REPL: ;; -;; > (slurp '"examples/http-sync.lfe") +;; $ ./bin/lfe +;; +;; lfe> (slurp "examples/http-sync.lfe") ;; #(ok http-sync) -;; > (get-pages (list '"http://lfe.github.io/")) +;; lfe> (get-pages (list "http://lfe.github.io/")) ;; Result: {{"HTTP/1.1",200,"OK"}, ;; {"cache-control","max-age=600"}, ;; {"connection","keep-alive"}, ;; ... ;; ok -;; > +;; lfe> ;; ;; The get-pages function starts the inets service for you. If you would like ;; to call get-page directly, you'll have to start that yourself: ;; -;; > (: inets start) -;; > (get-page '"http://lfe.github.io/") +;; lfe> (inets:start) +;; lfe> (ssl:start) +;; lfe> (get-page "http://lfe.github.io/") ;; Result: {{"HTTP/1.1",200,"OK"}, ;; {"cache-control","max-age=600"}, ;; {"connection","keep-alive"}, ;; ... ;; ok -;; > +;; lfe> (defmodule http-sync (export all)) @@ -88,8 +91,8 @@ ) In this example, the value assigned to the arg variable would be a list containing the values my-value-1 and my-value-2." - (let (((tuple 'ok data) (: init get_argument flag))) - (: lists merge data))) + (let (((tuple 'ok data) (init:get_argument flag))) + (lists:merge data))) (defun get-pages () "With no argument, assume 'url parameter was passed via command line." @@ -98,15 +101,16 @@ (defun get-pages (urls) "Start inets and make (potentially many) HTTP requests." - (: inets start) - (: lists map + (inets:start) + (ssl:start) + (lists:map (lambda (x) (get-page x)) urls)) (defun get-page (url) "Make a single HTTP request." - (case (: httpc request url) + (case (httpc:request url) ((tuple 'ok result) - (: io format '"Result: ~p~n" (list result))) + (io:format "Result: ~p~n" (list result))) ((tuple 'error reason) - (: io format '"Error: ~p~n" (list reason))))) + (io:format "Error: ~p~n" (list reason)))))
View file
_service:tar_scm:lfe-1.3.tar.gz/examples/internal-state.lfe -> _service:tar_scm:lfe-2.1.1.tar.gz/examples/internal-state.lfe
Changed
@@ -1,4 +1,4 @@ -;; Copyright (c) 2013, 2015 Duncan McGreggor <oubiwann@gmail.com> +;; Copyright (c) 2013-2020 Duncan McGreggor <oubiwann@gmail.com> ;; ;; Licensed under the Apache License, Version 2.0 (the "License"); ;; you may not use this file except in compliance with the License. @@ -22,60 +22,63 @@ ;; ;; To use the code below in LFE, do the following: ;; -;; $ ./bin/lfe -pa ./ebin +;; $ ./bin/lfe ;; -;; > (slurp "examples/internal-state.lfe") +;; lfe> (slurp "examples/internal-state.lfe") ;; #(ok internal-state) -;; > (set acct (new-account "Alice" 100.00 0.06)) +;; lfe> (set acct (new-account "Alice" 100.00 0.06)) ;; #Fun<lfe_eval.10.53503600> -;; > (send acct 'name) +;; lfe> (send acct 'name) ;; "Alice" -;; > (send acct 'balance) +;; lfe> (send acct 'balance) ;; 100.0 -;; > (set acct (send acct 'apply-interest)) +;; lfe> (set acct (send acct 'apply-interest)) ;; #Fun<lfe_eval.10.53503600> -;; > (send acct 'balance) +;; lfe> (send acct 'balance) ;; 106.0 -;; > (set acct (send acct 'withdraw 54.90)) +;; lfe> (set acct (send acct 'withdraw 54.90)) ;; #Fun<lfe_eval.10.53503600> -;; > (set acct (send acct 'withdraw 54.90)) +;; lfe> (set acct (send acct 'withdraw 54.90)) ;; exception error: insufficient-funds ;; -;; > (send acct 'balance) +;; lfe> (send acct 'balance) ;; 51.1 -;; > (set acct (send acct 'deposit 1000)) +;; lfe> (set acct (send acct 'deposit 1000)) ;; #Fun<lfe_eval.10.53503600> -;; > (set acct (send acct 'withdraw 54.90)) +;; lfe> (set acct (send acct 'withdraw 54.90)) ;; #Fun<lfe_eval.10.53503600> -;; > (set acct (send acct 'withdraw 54.90)) +;; lfe> (set acct (send acct 'withdraw 54.90)) ;; #Fun<lfe_eval.10.53503600> -;; > (set acct (send acct 'withdraw 54.90)) +;; lfe> (set acct (send acct 'withdraw 54.90)) ;; #Fun<lfe_eval.10.53503600> -;; > (send acct 'balance) +;; lfe> (send acct 'balance) ;; 886.4 -;; > (set acct (send acct 'apply-interest)) +;; lfe> (set acct (send acct 'apply-interest)) ;; #Fun<lfe_eval.10.53503600> -;; > (send acct 'balance) +;; lfe> (send acct 'balance) ;; 939.584 (defmodule internal-state - (export all)) + (export all)) (defun new-account (name balance interest-rate) (lambda (message) (case message ('withdraw (lambda (amt) - (if (=< amt balance) - (new-account name (- balance amt) interest-rate) - (error 'insufficient-funds)))) - ('deposit (lambda (amt) (new-account name (+ balance amt) interest-rate))) - ('balance (lambda () balance)) - ('name (lambda () name)) + (if (=< amt balance) + (new-account name (- balance amt) interest-rate) + (error 'insufficient-funds)))) + ('deposit (lambda (amt) + (new-account name (+ balance amt) interest-rate))) + ('balance (lambda () + balance)) + ('name (lambda () + name)) ('apply-interest (lambda () - (new-account - name - (+ balance (* balance interest-rate)) - interest-rate)))))) + (new-account + name + (+ balance (* balance interest-rate)) + interest-rate)))))) (defun send (object method-name) "This is a generic function, used to call into the given object (class @@ -90,21 +93,21 @@ ;; It is also possible to create functionally equivalent code using LFE ;; processes. The code below would then be used in the following manner: ;; -;; > (set acct (init-account "Alice" 1000 0.1)) +;; lfe> (set acct (init-account "Alice" 1000 0.1)) ;; <0.37.0> -;; > (snd acct 'name) +;; lfe> (snd acct 'name) ;; "Alice" -;; > (snd acct 'balance) +;; lfe> (snd acct 'balance) ;; 1000 -;; > (snd acct 'apply-interest) +;; lfe> (snd acct 'apply-interest) ;; 1.1e3 -;; > (snd acct 'deposit 1000) +;; lfe> (snd acct 'deposit 1000) ;; 2.1e3 -;; > (snd acct 'balance) +;; lfe> (snd acct 'balance) ;; 2.1e3 -;; > (snd acct 'withdraw 2000) +;; lfe> (snd acct 'withdraw 2000) ;; 100.0 -;; > (snd acct 'withdraw 101) +;; lfe> (snd acct 'withdraw 101) ;; #(error insufficient-funds) (defun account-class (name balance interest-rate)
View file
_service:tar_scm:lfe-1.3.tar.gz/examples/joes-fav.lfe -> _service:tar_scm:lfe-2.1.1.tar.gz/examples/joes-fav.lfe
Changed
@@ -1,5 +1,5 @@ ;; Copyright (c) 2013 Joe Armstrong <joearms@gmail.com>, Original Erlang version -;; Copyright (c) 2013 Duncan McGreggor <oubiwann@cogitat.io>, LFE version +;; Copyright (c) 2013-2020 Duncan McGreggor <oubiwann@gmail.com>, LFE version ;; ;; Licensed under the Apache License, Version 2.0 (the "License"); ;; you may not use this file except in compliance with the License. @@ -22,27 +22,28 @@ ;; ;; Here is some example usage: ;; -;; > (slurp '"examples/joes-fav.lfe") +;; $ ./bin/lfe +;; +;; lfe> (slurp "examples/joes-fav.lfe") ;; #(ok joes-fav) ;; ;; Quick sanity check: ;; -;; > (factorial 10) +;; lfe> (factorial 10) ;; 3628800 -;; > (factorial 20) +;; lfe> (factorial 20) ;; 2432902008176640000 -;; > (factorial 50) +;; lfe> (factorial 50) ;; 30414093201713378043612608166064768844377641568960512000000000000 ;; ;; Now, for the real thing: ;; -;; > (run-it) +;; lfe> (run-it) ;; 30414093201713378043612608166064768844377641568960512000000000000 ;; (defmodule joes-fav (export all)) - (defun universal-server () (receive ((tuple 'become server-function)
View file
_service:tar_scm:lfe-1.3.tar.gz/examples/lfe_eval.lfe -> _service:tar_scm:lfe-2.1.1.tar.gz/examples/lfe_eval.lfe
Changed
@@ -1,4 +1,4 @@ -;; Copyright (c) 2008-2013 Robert Virding +;; Copyright (c) 2008-2020 Robert Virding ;; ;; Licensed under the Apache License, Version 2.0 (the "License"); ;; you may not use this file except in compliance with the License. @@ -32,7 +32,7 @@ (from orddict (find 2) (store 3))) (deprecated #(eval 1) #(eval 2))) -(defun eval (e) (eval e (: lfe_env new))) +(defun eval (e) (eval e (lfe_env:new))) (defun eval (e env) (eval-expr e env)) @@ -42,16 +42,16 @@ ;; expr(Sexpr, Env) -> Value ;; Evaluate the sexpr, first expanding all macros. -(defun expr (e) (expr e (: lfe_env new))) +(defun expr (e) (expr e (lfe_env:new))) (defun expr (e env) - (let ((exp (: lfe_macro expand_expr_all e env))) + (let ((exp (lfe_macro:expand_expr_all e env))) (eval-expr exp env))) ;; gexpr(guardtest) -> Value ;; gexpr(guardtest, env) -> Value -(defun gexpr (gt) (gexpr gt (: lfe_env new))) +(defun gexpr (gt) (gexpr gt (lfe_env:new))) (defun gexpr (gt env) (eval-gexpr gt env)) @@ -62,7 +62,7 @@ ;; internally. Args should already be evaluated. (defun apply (f args) - (apply f args (: lfe_env new))) + (apply f args (lfe_env:new))) (defun apply (f args env) (eval-apply-expr f args env)) @@ -72,11 +72,11 @@ ;; (guard guard) -> true | false ;; (guard guard env) -> true | false -(defun body (b) (body b (: lfe_env new))) +(defun body (b) (body b (lfe_env:new))) (defun body (b env) (eval-body b env)) -(defun guard (g) (guard g (: lfe_env new))) +(defun guard (g) (guard g (lfe_env:new))) (defun guard (g env) (eval-guard g env)) @@ -125,7 +125,7 @@ ((cons 'try body) (eval-try body env)) ((list* 'funcall f as) - (: erlang apply (eval-expr f env) (eval-list as env))) + (erlang:apply (eval-expr f env) (eval-list as env))) ((cons 'call body) (eval-call body env)) ;; General function calls. @@ -133,19 +133,19 @@ ;; Note that macros have already been expanded here. (let ((ar (length es))) ;Arity (case (get_fbinding fun ar env) - ((tuple 'yes m f) (: erlang apply m f (eval-list es env))) + ((tuple 'yes m f) (erlang:apply m f (eval-list es env))) ((tuple 'yes f) (eval-apply f (eval-list es env) env)) - ('no (: erlang error (tuple 'unbound_func (tuple fun ar))))))) + ('no (erlang:error (tuple 'unbound_func (tuple fun ar))))))) ((cons f es) - (: erlang error (tuple 'bad_form 'application))) + (erlang:error (tuple 'bad_form 'application))) (e (if (is_atom e) (case (get_vbinding e env) ((tuple 'yes val) val) - (no (: erlang error (tuple 'unbound_symb e)))) + (no (erlang:error (tuple 'unbound_symb e)))) e)))) ;Atoms evaluate to themselves (defun eval-list (es env) - (: lists map (lambda (e) (eval-expr e env)) es)) + (lists:map (lambda (e) (eval-expr e env)) es)) (defun eval-body (body env) (case body @@ -263,7 +263,7 @@ ((list 'unit n) (when (is_integer n) (> n 0)) (set-spec-unit sp n)) ;; Illegal spec. - (_ (: erlang error (tuple 'illegal_bitspec spec))))) + (_ (erlang:error (tuple 'illegal_bitspec spec))))) ;; (eval-exp-bitseg value type size unit sign endian) -> binary(). @@ -282,7 +282,7 @@ (case (bit_size val) (size (when (=:= (rem size un) 0)) (binary (val bitstring (size size)))) - (_ (: erlang error 'bad_arg)))) + (_ (erlang:error 'bad_arg)))) ((tuple 'binary sz un _ _) (binary (val bitstring (size (* sz un))))))) @@ -343,8 +343,7 @@ (14 (lambda (a b c d e f g h i j k l m n) (apply-lambda args body (list a b c d e f g h i j k l m n) env))) (15 (lambda (a b c d e f g h i j k l m n o) - (apply-lambda args body (list a b c d e f g h i j k l m n o) env))) - ))) + (apply-lambda args body (list a b c d e f g h i j k l m n o) env)))))) (defun apply-lambda (args body vals env) (fletrec ((bind-args @@ -386,8 +385,7 @@ (14 (lambda (a b c d e f g h i j k l m n) (apply-match-clauses cls (list a b c d e f g h i j k l m n) env))) (15 (lambda (a b c d e f g h i j k l m n o) - (apply-match-clauses cls (list a b c d e f g h i j k l m n o) env))) - )) + (apply-match-clauses cls (list a b c d e f g h i j k l m n o) env))))) (defun match-lambda-arity (cls) (length (caar cls))) @@ -401,8 +399,8 @@ (case (match-when (cons 'list pats) as body env) ((tuple 'yes body1 vbs) (eval-body body1 (add_vbindings vbs env))) ('no (apply-match-clauses cls as env))) - (: erlang error 'badarity))) - (_ (: erlang error 'function_clause)))) + (erlang:error 'badarity))) + (_ (erlang:error 'function_clause)))) ;; (eval-let (PatBindings . Body) Env) -> Value. @@ -414,13 +412,13 @@ (let ((val (eval-expr e env0))) (case (match pat val env0) ((tuple 'yes bs) (add_vbindings bs env)) - ('no (: erlang error (tuple 'badmatch val)))))) + ('no (erlang:error (tuple 'badmatch val)))))) ((list pat (= (cons 'when _) g) e) env (let ((val (eval-expr e env0))) (case (match-when pat val (list g) env0) ((tuple 'yes '() bs) (add_vbindings bs env)) - ('no (: erlang error (tuple 'badmatch val)))))) - (_ _ (: erlang error (tuple 'bad_form 'let)))) + ('no (erlang:error (tuple 'badmatch val)))))) + (_ _ (erlang:error (tuple 'bad_form 'let)))) env0 vbs))) (eval-body b env))) @@ -437,7 +435,7 @@ ((list v (= (list* 'match-lambda (cons pats _) _) f)) e (when (is_atom v)) (add v (length pats) f env0 e)) - (_ _ (: erlang error (tuple 'bad_form 'let-function)))) + (_ _ (erlang:error (tuple 'bad_form 'let-function)))) env0 fbs))) (eval-body body env)))) @@ -454,8 +452,8 @@ ((list v (= (list* 'match-lambda (cons pats _) _) f)) (when (is_atom v)) (tuple v (length pats) f)) - (_ (: erlang error (tuple 'bad_form 'letrec-function))))) - (fbs1 (: lists map map-fun fbs0)) + (_ (erlang:error (tuple 'bad_form 'letrec-function))))) + (fbs1 (lists:map map-fun fbs0)) (env1 (make_letrec_env fbs1 env0))) (eval-body body env1))) @@ -472,7 +470,7 @@ (defun init_letrec_env (env) (tuple () env)) (defun make_letrec_env (fbs0 env) - (let ((fbs (: lists map (lambda (fb) + (let ((fbs (lists:map (lambda (fb) (let (((tuple v ar body) fb)) (tuple v ar (tuple 'letrec body fbs0 env)))) fbs0))) @@ -513,10 +511,10 @@ ;; Macros are expanded first. (defun eval-apply-expr (func es env) - (case (: lfe_macro expand_expr_all func env) + (case (lfe_macro:expand_expr_all func env) ((list* 'lambda args body) (apply-lambda args body es env)) ((cons 'match-lambda cls) (apply-match-clauses cls es env)) - (fun (when (is_function fun)) (: erlang apply fun es)))) + (fun (when (is_function fun)) (erlang:apply fun es)))) ;; (eval-if body env) -> value
View file
_service:tar_scm:lfe-1.3.tar.gz/examples/messenger-back.lfe -> _service:tar_scm:lfe-2.1.1.tar.gz/examples/messenger-back.lfe
Changed
@@ -1,10 +1,10 @@ -;; Copyright (c) 2013 Duncan McGreggor <oubiwann@cogitat.io> +;; Copyright (c) 2013-2020 Duncan McGreggor <oubiwann@cogitat.io> ;; ;; Licensed under the Apache License, Version 2.0 (the "License"); ;; you may not use this file except in compliance with the License. ;; You may obtain a copy of the License at ;; -;; http://www.apache.org/licenses/LICENSE-2.0 +;; http://www.apache.org/licenses/LICENSE-2.0 ;; ;; Unless required by applicable law or agreed to in writing, software ;; distributed under the License is distributed on an "AS IS" BASIS, @@ -15,46 +15,49 @@ ;; File : messenger-back.lfe ;; Author : Duncan McGreggor ;; Purpose : Demonstrating bidirectional message passing between the shell and -;; a spawned process. +;; a spawned process. ;; This file contains a simple demo for passing messages to an Erlang process ;; in LFE and the sending a message back to the calling process. To use, do the ;; following: ;; -;; $ ./bin/lfe -pa ./ebin -;; > (c '"examples/messenger-back") -;; #(module messenger-back) -;; > (: messenger-back send-message (self) '"Well, I was able to extend the original entry a bit, yes.") -;; #(<0.25.0> "Well, I was able to extend the original entry a bit, yes.") -;; Received message: 'Well, I was able to extend the original entry a bit, yes.' -;; > Sending message to process <0.25.0> ... -;; (: messenger-back send-message (self) '"And what does it say now?") -;; #(<0.25.0> "And what does it say now?") -;; Received message: 'And what does it say now?' -;; > Sending message to process <0.25.0> ... -;; (: messenger-back send-message (self) '"Mostly harmless.") -;; #(<0.25.0> "Mostly harmless.") -;; Received message: 'Mostly harmless.' -;; > Sending message to process <0.25.0> ... +;; $ ./bin/lfe +;; +;; lfe> (c "examples/messenger-back") +;; #(module messenger-back) +;; lfe> (messenger-back:send-message (self) "Well, I was able to extend the original entry a bit, yes.") +;; #(<0.25.0> "Well, I was able to extend the original entry a bit, yes.") +;; Received message: 'Well, I was able to extend the original entry a bit, yes.' +;; lfe> Sending message to process <0.25.0> ... +;; (messenger-back:send-message (self) "And what does it say now?") +;; #(<0.25.0> "And what does it say now?") +;; Received message: 'And what does it say now?' +;; lfe> Sending message to process <0.25.0> ... +;; (messenger-back:send-message (self) "Mostly harmless.") +;; #(<0.25.0> "Mostly harmless.") +;; Received message: 'Mostly harmless.' +;; lfe> Sending message to process <0.25.0> ... ;; With the messages sent and then resent back to the process whose ID was ;; presented, we can check to see that the calling process received the ;; information, as planned: ;; -;; > (: c flush) -;; Shell got {"Well, I was able to extend the original entry a bit, yes."} -;; Shell got {"And what does it say now?"} -;; Shell got {"Mostly harmless."} -;; > +;; lfe> (c:flush) +;; Shell got {"Well, I was able to extend the original entry a bit, yes."} +;; Shell got {"And what does it say now?"} +;; Shell got {"Mostly harmless."} +;; lfe> ;; (defmodule messenger-back - (export (print-result 0) (send-message 2))) + (export + (print-result 0) + (send-message 2))) (defun print-result () (receive ((tuple pid msg) - (: io format '"Received message: '~s'~n" (list msg)) - (: io format '"Sending message to process ~p ...~n" (list pid)) + (io:format "Received message: '~s'~n" (list msg)) + (io:format "Sending message to process ~p ...~n" (list pid)) (! pid (tuple msg)) (print-result))))
View file
_service:tar_scm:lfe-1.3.tar.gz/examples/messenger.lfe -> _service:tar_scm:lfe-2.1.1.tar.gz/examples/messenger.lfe
Changed
@@ -1,4 +1,4 @@ -;; Copyright (c) 2013 Duncan McGreggor <oubiwann@cogitat.io> +;; Copyright (c) 2013-2020 Duncan McGreggor <oubiwann@cogitat.io> ;; ;; Licensed under the Apache License, Version 2.0 (the "License"); ;; you may not use this file except in compliance with the License. @@ -19,26 +19,28 @@ ;; This file contains a simple demo for passing messages to an Erlang process ;; in LFE. To use, do the following: ;; -;; $ ../bin/lfe -pa ../ebin -;; > (c '"messenger") -;; #(module messenger) -;; > (set pid (spawn 'messenger 'print-result ())) -;; <0.34.0> -;; > (! pid '"Zaphod was here.") -;; "Zaphod was here." -;; Received message: 'Zaphod was here.' -;; > (! pid '"Ford is missing.") -;; "Ford is missing." -;; Received message: 'Ford is missing.' -;; > (! pid '"Arthur is pining for Trillian.") -;; "Arthur is pining for Trillian." -;; Received message: 'Arthur is pining for Trillian.' +;; $ ./bin/lfe +;; +;; lfe> (c "examples/messenger") +;; #(module messenger) +;; lfe> (set pid (spawn 'messenger 'print-result ())) +;; <0.34.0> +;; lfe> (! pid "Zaphod was here.") +;; "Zaphod was here." +;; Received message: 'Zaphod was here.' +;; lfe> (! pid "Ford is missing.") +;; "Ford is missing." +;; Received message: 'Ford is missing.' +;; lfe> (! pid "Arthur is pining for Trillian.") +;; "Arthur is pining for Trillian." +;; Received message: 'Arthur is pining for Trillian.' (defmodule messenger - (export (print-result 0))) + (export + (print-result 0))) (defun print-result () (receive (msg - (: io format '"Received message: '~s'~n" (list msg)) + (io:format "Received message: '~s'~n" (list msg)) (print-result))))
View file
_service:tar_scm:lfe-1.3.tar.gz/examples/mnesia_demo.lfe -> _service:tar_scm:lfe-2.1.1.tar.gz/examples/mnesia_demo.lfe
Changed
@@ -1,4 +1,4 @@ -;; Copyright (c) 2008-2013 Robert Virding +;; Copyright (c) 2008-2020 Robert Virding ;; ;; Licensed under the Apache License, Version 2.0 (the "License"); ;; you may not use this file except in compliance with the License. @@ -21,8 +21,27 @@ ;; together with mnesia:match_object, match specifications with ;; mnesia:select and Query List Comprehensions. +;; $ ./bin/lfe +;; +;; lfe> (c "examples/mnesia_demo.lfe") +;; +;; lfe> (set db (mnesia_demo:new)) +;; ok +;; lfe> (mnesia_demo:by_place 'london) +;; #(atomic +;; (#(person paul london driver) +;; #(person fred london waiter) +;; #(person john london painter) +;; #(person bert london waiter))) + (defmodule mnesia_demo - (export (new 0) (by_place 1) (by_place_ms 1) (by_place_qlc 1))) + (export + (new 0) + (by_place 1) + (by_place_ms 1) + ;; XXX - Currently broken; see https://github.com/lfe/lfe/issues/397 + ;; (by_place_qlc 1) + )) (defrecord person name @@ -31,8 +50,8 @@ (defun new () ;; Start mnesia and create a table, we will get an in memory only schema. - (: mnesia start) - (: mnesia create_table + (mnesia:start) + (mnesia:create_table 'person `(#(attributes ,(fields-person)))) ;; Initialise the table. @@ -55,37 +74,38 @@ #(fritz berlin painter) #(kurt berlin driver) #(hans berlin waiter) - #(franz berlin waiter) - ))) - (: lists foreach (match-lambda - ((tuple n p j) - (: mnesia transaction - (lambda () - (let ((new (make-person name n place p job j))) - (: mnesia write new)))))) - people))) + #(franz berlin waiter)))) + (lists:foreach + (match-lambda + ((tuple n p j) + (mnesia:transaction + (lambda () + (let ((new (make-person name n place p job j))) + (mnesia:write new)))))) + people))) ;; Match records by place using match_object and the emp-XXXX macro. (defun by_place (place) - (: mnesia transaction - (lambda () (: mnesia match_object (emp-person place place))))) + (mnesia:transaction + (lambda () (mnesia:match_object (emp-person place place))))) ;; Use match specifications to match records (defun by_place_ms (place) - (let ((f (lambda () (: mnesia select 'person + (let ((f (lambda () (mnesia:select 'person (match-spec ((match-person name n place p job j) (when (=:= p place)) (tuple n j))))))) - (: mnesia transaction f))) + (mnesia:transaction f))) +;; XXX - Currently broken; see https://github.com/lfe/lfe/issues/397 ;; Use Query List Comprehensions to match records -(defun by_place_qlc (place) - (let ((f (lambda () - (let ((q (qlc (lc ((<- person (: mnesia table 'person)) - (=:= (person-place person) place)) - person)))) - (: qlc e q))))) - (: mnesia transaction f))) +;; (defun by_place_qlc (place) +;; (let ((f (lambda () +;; (let ((q (qlc (lc ((<- person (mnesia:table 'person)) +;; (=:= (person-place person) place)) +;; person)))) +;; (qlc:e q))))) +;; (mnesia:transaction f))) ;; Ignore this ;; (qlc ((<- A (call 'qlc 'q (tuple 'qlc_lc (match-lambda (() (tuple 'simple_v1 'X (match-lambda (() (cons 1 (cons 2 (cons 3 ()))))) 42))) 'undefined)))) A)
View file
_service:tar_scm:lfe-1.3.tar.gz/examples/object-via-closure.lfe -> _service:tar_scm:lfe-2.1.1.tar.gz/examples/object-via-closure.lfe
Changed
@@ -1,4 +1,4 @@ -;; Copyright (c) 2013 Duncan McGreggor <oubiwann@gmail.com> +;; Copyright (c) 2013-2020 Duncan McGreggor <oubiwann@gmail.com> ;; ;; Licensed under the Apache License, Version 2.0 (the "License"); ;; you may not use this file except in compliance with the License. @@ -26,61 +26,61 @@ ;; ;; To use the code below in LFE, do the following: ;; -;; $ .bin/lfe -pa .ebin +;; $ ./bin/lfe ;; ;; Load the file and create a fish-class instance: ;; -;; > (slurp "examples/object-via-closure.lfe") +;; lfe> (slurp "examples/object-via-closure.lfe") ;; #(ok object-via-closure) -;; > (set mommy-fish (fish-class "Carp")) +;; lfe> (set mommy-fish (fish-class "Carp")) ;; #Fun<lfe_eval.10.91765564> ;; ;; Execute some of the basic methods: ;; -;; > (send mommy-fish 'species) +;; lfe> (send mommy-fish 'species) ;; "Carp" -;; > (send mommy-fish 'move 17) +;; lfe> (send mommy-fish 'move 17) ;; The Carp swam 17 feet! ;; ok -;; > (send mommy-fish 'id) -;; "47eebe91a648f042fc3fb278df663de5" +;; lfe> (send mommy-fish 'id) +;; "c0ec94b9de24657c51ba180768542b27" ;; ;; Now let's look at "modifying" state data (e.g., children counts): ;; -;; > (send mommy-fish 'children) +;; lfe> (send mommy-fish 'children) ;; () -;; > (send mommy-fish 'children-count) +;; lfe> (send mommy-fish 'children-count) ;; 0 -;; > (set `(,mommy-fish ,baby-fish-1) (send mommy-fish 'reproduce)) +;; lfe> (set `(,mommy-fish ,baby-fish-1) (send mommy-fish 'reproduce)) ;; (#Fun<lfe_eval.10.91765564> #Fun<lfe_eval.10.91765564>) -;; > (send mommy-fish 'id) -;; "47eebe91a648f042fc3fb278df663de5" -;; > (send baby-fish-1 'id) -;; "fdcf35983bb496650e558a82e34c9935" -;; > (send mommy-fish 'children-count) +;; lfe> (send mommy-fish 'id) +;; "c0ec94b9de24657c51ba180768542b27" +;; lfe> (send baby-fish-1 'id) +;; "5f31a47f000b5d173faa2793ea2ec876" +;; lfe> (send mommy-fish 'children-count) ;; 1 -;; > (set `(,mommy-fish ,baby-fish-2) (send mommy-fish 'reproduce)) +;; lfe> (set `(,mommy-fish ,baby-fish-2) (send mommy-fish 'reproduce)) ;; (#Fun<lfe_eval.10.91765564> #Fun<lfe_eval.10.91765564>) -;; > (send baby-fish-2 'id) -;; "3e64e5c20fb742dd88dac1032749c2fd" -;; > (send mommy-fish 'children-count) +;; lfe> (send baby-fish-2 'id) +;; "2f40b14a4394f3b7a57d4e9048bbb19e" +;; lfe> (send mommy-fish 'children-count) ;; 2 -;; > (send mommy-fish 'info) -;; id: "47eebe91a648f042fc3fb278df663de5" -;; species: "Carp" -;; children: "fdcf35983bb496650e558a82e34c9935", -;; "3e64e5c20fb742dd88dac1032749c2fd" +;; lfe> (send mommy-fish 'info) +;; (#(id "c0ec94b9de24657c51ba180768542b27") +;; #(species "Carp") +;; #(children +;; ("5f31a47f000b5d173faa2793ea2ec876" "2f40b14a4394f3b7a57d4e9048bbb19e"))) ;; ok (defmodule object-via-closure - (export all)) + (export all)) (defun fish-class (species) "This is the constructor that will be used most often, only requiring that one pass a 'species' string. When the children are not defined, simply use an empty list." - (fish-class species ())) + (fish-class species '())) (defun fish-class (species children) "This contructor is mostly useful as a way of abstracting out the id @@ -88,10 +88,7 @@ besides fish-class/1, so it's not strictly necessary. When the id isn't known, generate one." - (let* (((binary (id (size 128))) (crypto:rand_bytes 16)) - (formatted-id (car - (io_lib:format "~32.16.0b" (list id))))) - (fish-class species children formatted-id))) + (fish-class species children (gen-id))) (defun fish-class (species children id) "This is the constructor used internally, once the children and fish id are @@ -107,10 +104,9 @@ (lambda (self) children)) ('info (lambda (self) - (io:format "id: ~p~nspecies: ~p~nchildren: ~p~n" - `(,(send self 'id) - ,(send self 'species) - ,(send self 'children))))) + `(#(id ,(send self 'id)) + #(species ,(send self 'species)) + #(children ,(send self 'children))))) ('move (lambda (self distance) (io:format "The ~s ~s ~p feet!~n" @@ -135,4 +131,9 @@ (defun send (object method-name arg) "This is a generic function, used to call into the given object (class instance)." - (funcall (funcall object method-name) object arg)) \ No newline at end of file + (funcall (funcall object method-name) object arg)) + +(defun gen-id () + (let (((binary (id (size 128))) (crypto:strong_rand_bytes 16))) + (io_lib:format "~32.16.0b" (list id)))) +
View file
_service:tar_scm:lfe-1.3.tar.gz/examples/object-via-process.lfe -> _service:tar_scm:lfe-2.1.1.tar.gz/examples/object-via-process.lfe
Changed
@@ -1,4 +1,4 @@ -;; Copyright (c) 2013 Duncan McGreggor <oubiwann@gmail.com> +;; Copyright (c) 2013-2020 Duncan McGreggor <oubiwann@gmail.com> ;; ;; Licensed under the Apache License, Version 2.0 (the "License"); ;; you may not use this file except in compliance with the License. @@ -26,50 +26,50 @@ ;; ;; To use the code below in LFE, do the following: ;; -;; $ ./bin/lfe -pa ./ebin +;; $ ./bin/lfe ;; ;; Load the file and create a fish-class instance: ;; -;; > (slurp "examples/object-via-process.lfe") +;; lfe> (slurp "examples/object-via-process.lfe") ;; #(ok object-via-process) -;; > (set mommy-fish (init-fish "Carp")) -;; <0.33.0> +;; lfe> (set mommy-fish (init-fish "Carp")) +;; #Pid<0.33.0> ;; ;; Execute some of the basic methods: ;; -;; > (send mommy-fish 'species) +;; lfe> (send mommy-fish 'species) ;; "Carp" -;; > (send mommy-fish 'move 17) +;; lfe> (send mommy-fish 'move 17) ;; "The Carp swam 17 feet!" -;; > (send mommy-fish 'id) +;; lfe> (send mommy-fish 'id) ;; "47eebe91a648f042fc3fb278df663de5" ;; ;; Now let's look at modifying state data (e.g., children counts): ;; -;; > (send mommy-fish 'children) +;; lfe> (send mommy-fish 'children) ;; () -;; > (send mommy-fish 'children-count) +;; lfe> (send mommy-fish 'children-count) ;; 0 -;; > (set baby-fish-1 (send mommy-fish 'reproduce)) -;; <0.34.0> -;; > (send baby-fish-1 'id) +;; lfe> (set baby-fish-1 (send mommy-fish 'reproduce)) +;; #Pid<0.34.0> +;; lfe> (send baby-fish-1 'id) ;; "fdcf35983bb496650e558a82e34c9935" -;; > (send mommy-fish 'children-count) +;; lfe> (send mommy-fish 'children-count) ;; 1 -;; > (set baby-fish-2 (send mommy-fish 'reproduce)) -;; <0.35.0> -;; > (send baby-fish-2 'id) +;; lfe> (set baby-fish-2 (send mommy-fish 'reproduce)) +;; #Pid<0.35.0> +;; lfe> (send baby-fish-2 'id) ;; "3e64e5c20fb742dd88dac1032749c2fd" -;; > (send mommy-fish 'children-count) +;; lfe> (send mommy-fish 'children-count) ;; 2 -;; > (send mommy-fish 'info) +;; lfe> (send mommy-fish 'info) ;; (#(id "f05064ffcf92d7b3e72968fd481abbd0") ;; #(species "Carp") ;; #(children ;; ("d53a426c732c938f996a1c2520bb621f" "15fede691ab3f96e9e3df248d37b7b55"))) (defmodule object-via-process - (export all)) + (export all)) (defun init-fish (species) "This is the constructor that will be used most often, only requiring that @@ -83,11 +83,8 @@ 1) as a way of abstracting out the id generation from the larger constructor, and 2) spawning the 'object loop' code (fish-class/3)." - (let* (((binary (id (size 128))) (crypto:rand_bytes 16)) - (formatted-id (car - (io_lib:format "~32.16.0b" `(,id))))) (spawn (lambda () - (fish-class species children formatted-id))))) + (fish-class species children (gen-id))))) (defun fish-class (species children id) "This function is intended to be spawned as a separate process which is @@ -135,3 +132,7 @@ (! object `#(,(self) ,method-name ,arg)) (receive (data data))) + +(defun gen-id () + (let (((binary (id (size 128))) (crypto:strong_rand_bytes 16))) + (io_lib:format "~32.16.0b" (list id))))
View file
_service:tar_scm:lfe-1.3.tar.gz/examples/ping_pong.lfe -> _service:tar_scm:lfe-2.1.1.tar.gz/examples/ping_pong.lfe
Changed
@@ -1,4 +1,4 @@ -;; Copyright (c) Tim Dysinger tim <<-on->> dysinger.net +;; Copyright (c) 2009-2020 Tim Dysinger tim <<-on->> dysinger.net ;; Permission is hereby granted, free of charge, to any person obtaining a copy ;; of this software and associated documentation files (the "Software"), to deal @@ -18,41 +18,75 @@ ;; OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN ;; THE SOFTWARE. +;; To use the code below in LFE, do the following: +;; +;; $ ./bin/lfe +;; +;; Compile this example and run it: +;; +;; lfe> (c "examples/ping_pong.lfe") +;; (#(module ping_pong)) +;; lfe> (ping_pong:start_link) +;; #(ok #Pid<0.196.0>) +;; lfe> (ping_pong:ping) +;; #(pong 1) +;; lfe> (ping_pong:stop) +;; ok + (defmodule ping_pong - (export (start_link 0) (ping 0)) - (export (init 1) (handle_call 3) (handle_cast 2) - (handle_info 2) (terminate 2) (code_change 3)) - (behaviour gen_server)) ;Just indicates intent + (export + (start_link 0) + (start 0) + (stop 0) + (ping 0)) + (export + (init 1) + (handle_call 3) + (handle_cast 2) + (handle_info 2) + (terminate 2) + (code_change 3)) + (behaviour gen_server)) ; Just indicates intent + +;; Management API (defun start_link () - (: gen_server start_link - (tuple 'local 'ping_pong) 'ping_pong (list) (list))) + (gen_server:start_link + #(local ping_pong) 'ping_pong '() '())) + +(defun start () + (gen_server:start + #(local ping_pong) 'ping_pong '() '())) + +(defun stop () + (gen_server:stop 'ping_pong)) ;; Client API (defun ping () - (: gen_server call 'ping_pong 'ping)) + (gen_server:call 'ping_pong 'ping)) ;; Gen_server callbacks -(defrecord state (pings 0)) +(defrecord state + (pings 0)) (defun init (args) - (tuple 'ok (make-state pings 0))) + `#(ok ,(make-state pings 0))) (defun handle_call (req from state) (let* ((new-count (+ (state-pings state) 1)) (new-state (set-state-pings state new-count))) - (tuple 'reply (tuple 'pong new-count) new-state))) + `#(reply #(pong ,new-count) ,new-state))) (defun handle_cast (msg state) - (tuple 'noreply state)) + `#(noreply ,state)) (defun handle_info (info state) - (tuple 'noreply state)) + `#(noreply ,state)) (defun terminate (reason state) 'ok) (defun code_change (old-vers state extra) - (tuple 'ok state)) + `#(ok ,state))
View file
_service:tar_scm:lfe-1.3.tar.gz/examples/ring.lfe -> _service:tar_scm:lfe-2.1.1.tar.gz/examples/ring.lfe
Changed
@@ -1,4 +1,4 @@ -;; Copyright (c) 2014 Duncan McGreggor <oubiwann@cogitat.io> +;; Copyright (c) 2014-2020 Duncan McGreggor <oubiwann@gmail.com> ;; ;; Licensed under the Apache License, Version 2.0 (the "License"); ;; you may not use this file except in compliance with the License. @@ -31,13 +31,14 @@ ;; ;; To use the code below in LFE, do the following: ;; -;; $ make compile -;; $ cd examples -;; $ ../bin/lfe -pa ../ebin -smp disable -noshell -run ring main 503 50000000 +;; $ ./bin/lfe ;; -;; This should give the following output: +;; Compile this example and run it: ;; -;; Result: 292 +;; lfe> (c "examples/ring.lfe") +;; (#(module ring)) +;; lfe> (ring:main '(503 50000000)) +;; Result:: 292 ;; (defmodule ring (export @@ -45,9 +46,7 @@ (roundtrip 2))) (defun main (args) - (apply - #'start-ring/2 - (lists:map #'list_to_integer/1 args))) + (apply #'start-ring/2 args)) (defun start-ring (process-count traversal-count) (let ((batch (make-processes process-count traversal-count))) @@ -61,12 +60,12 @@ (lists:seq process-count 2 -1))) (defun make-process (id pid) - (spawn 'ring 'roundtrip (list id pid))) + (spawn 'ring 'roundtrip `(,id ,pid))) (defun roundtrip (id pid) (receive (1 - (io:fwrite '"Result: ~b~n" (list id)) + (io:fwrite "Result: ~b~n" `(,id)) (erlang:halt)) (data (! pid (- data 1))
View file
_service:tar_scm:lfe-1.3.tar.gz/examples/sample-lfe-shellscript -> _service:tar_scm:lfe-2.1.1.tar.gz/examples/sample-lfe-shellscript
Changed
@@ -2,7 +2,7 @@ ;; -*- mode: lfe -*- ;;! -smp enable -sname factorial -mnesia debug verbose ;; -;; Copyright (c) 2013 Duncan McGreggor <oubiwann@cogitat.io> +;; Copyright (c) 2013-2020 Duncan McGreggor <oubiwann@gmail.com> ;; ;; Licensed under the Apache License, Version 2.0 (the "License"); ;; you may not use this file except in compliance with the License. @@ -21,10 +21,11 @@ ;; Purpose : Demonstrating usage of lfe ;; To use this script make sure you have run "make install" from the -;; lfe working directory +;; lfe working directory and then (temporarily) set the PATH: ;; ;; At this point, you can call this script directly: ;; +;; $ export PATH=$(pwd)/bin:$PATH ;; $ examples/sample-lfe-shellscript ;; usage: examples/sample-lfescript <integer> ;; @@ -39,7 +40,7 @@ (n (* n (fac (- n 1))))) (defun usage () - (: lfe_io format "usage: ~s <integer>\n" (list script-name))) + (lfe_io:format "usage: ~s <integer>\n" (list script-name))) ;; Now do it (case script-args @@ -47,7 +48,7 @@ (try (let* ((n (list_to_integer string)) (f (fac n))) - (: lfe_io format '"factorial ~w = ~w\n" (list n f))) + (lfe_io:format "factorial ~w = ~w\n" (list n f))) (catch ((tuple _ _ _) (usage))))) (() (usage)))
View file
_service:tar_scm:lfe-1.3.tar.gz/examples/sample-lfescript -> _service:tar_scm:lfe-2.1.1.tar.gz/examples/sample-lfescript
Changed
@@ -2,7 +2,7 @@ ;; -*- mode: lfe -*- ;;! -smp enable -sname factorial -mnesia debug verbose ;; -;; Copyright (c) 2013 Duncan McGreggor <oubiwann@cogitat.io> +;; Copyright (c) 2013-2020 Duncan McGreggor <oubiwann@gmail.com> ;; ;; Licensed under the Apache License, Version 2.0 (the "License"); ;; you may not use this file except in compliance with the License. @@ -25,6 +25,7 @@ ;; ;; At this point, you can call this script directly: ;; +;; $ export PATH=$(pwd)/bin:$PATH ;; $ examples/sample-lfescript ;; usage: examples/sample-lfescript <integer> ;; @@ -41,7 +42,7 @@ (try (let* ((n (list_to_integer string)) (f (fac n))) - (: lfe_io format '"factorial ~w = ~w\n" (list n f))) + (lfe_io:format "factorial ~w = ~w\n" (list n f))) (catch ((tuple _ _ _) (usage))))) (_ (usage))) @@ -51,5 +52,5 @@ (n (* n (fac (- n 1))))) (defun usage () - (let ((script-name (: escript script_name))) - (: lfe_io format '"usage: ~s <integer>\n" (list script-name)))) + (let ((script-name (escript:script_name))) + (lfe_io:format "usage: ~s <integer>\n" (list script-name))))
View file
_service:tar_scm:lfe-1.3.tar.gz/examples/simple-erl-exercises.lfe -> _service:tar_scm:lfe-2.1.1.tar.gz/examples/simple-erl-exercises.lfe
Changed
@@ -1,4 +1,4 @@ -;; Copyright (c) 2008-2013 Sean Chalmers +;; Copyright (c) 2008-2020 Sean Chalmers ;; ;; Licensed under the Apache License, Version 2.0 (the "License"); ;; you may not use this file except in compliance with the License. @@ -35,15 +35,16 @@ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; (defmodule exercises - (export (convert 1) - (perimeter 1) - (min 1) - (max 1) - (min_max 1) - (min_max2 1) - (start_pong 1) - (start_ring 2) - (start_star 2))) + (export + (convert 1) + (perimeter 1) + (min 1) + (max 1) + (min_max 1) + (min_max2 1) + (start_pong 1) + (start_ring 2) + (start_star 2))) ;; SIMPLE SEQUENTIAL EXERCISES @@ -66,7 +67,7 @@ (tuple 'square (* 4 side))) ;; Circle ((tuple 'circle radius) (when (is_number radius)) - (tuple 'circle (: math pow (* (: math pi) radius) 2))) + (tuple 'circle (math:pow (* (math:pi) radius) 2))) ;; Triangle ((tuple 'triangle a b c) (when (is_number a) (is_number b) @@ -79,10 +80,10 @@ ;; I know lists:max/1 and lists:min/1 exist, that isn't the point. (defun min ((cons x xs) - (: lists foldl (fun erlang min 2) x xs))) + (lists:foldl (fun erlang min 2) x xs))) (defun max ((cons x xs) - (: lists foldl (fun erlang max 2) x xs))) + (lists:foldl (fun erlang max 2) x xs))) (defun min_max (col) ;; Flavourless min_max/1 implementation. @@ -90,7 +91,7 @@ ;; Alternative min_max without the little helpers (defun min_max2 (col) - (let-function (gief (match-lambda (f (cons x xs) (: lists foldl f x xs)))) + (let-function (gief (match-lambda (f (cons x xs) (lists:foldl f x xs)))) ;; Create a tuple using our temp function above. (tuple (gief (fun erlang min 2) col) (gief (fun erlang max 2) col)))) @@ -104,16 +105,16 @@ ((list a b) (list a b))) (defun swedish_date () - (: lists foldl ;; I heart fold + (lists:foldl ;; I heart fold (lambda (x acc) (++ acc (nom-date (integer_to_list x)))) () ;; This is our accumulator - (tuple_to_list (: erlang date)))) + (tuple_to_list (erlang:date)))) (defun create-pids-one-arg (fn arg col) ;; I ended up using this pattern a few times in the next couple of ;; exercises so I pulled it out into it's own function. - (: lists map (lambda (_) (spawn (MODULE) fn (list arg))) col)) + (lists:map (lambda (_) (spawn (MODULE) fn (list arg))) col)) (defun pong (n) ;; This is the pong receiver. @@ -125,7 +126,7 @@ 'ok) ;; We've received a message, bump the counter and send it back. ((tuple 'ping from count) - (: io format '"caught ball~n" (list)) + (io:format "caught ball~n" (list)) (! from (tuple 'ping (self) (+ count 1))) ;; Make sure we're still here to get the next message. (pong n)))) @@ -139,7 +140,7 @@ (defun start_ring (n-rings n-msgs) ;; Create the desired number of "servers" in the ring. (let ((cons x xs) - (create-pids-one-arg 'ring n-msgs (: lists seq 1 n-rings))) + (create-pids-one-arg 'ring n-msgs (lists:seq 1 n-rings))) ;; Get it rolling. (! x (tuple 'pass (++ xs (list x)) 0)))) @@ -151,12 +152,12 @@ ;; We've reached the maxiumum number of messages ((tuple 'pass (cons x xs) msg) (when (== msg n-msgs)) ;; State our intentions. - (: io format '"Shutting Down.~n" '()) + (io:format "Shutting Down.~n" '()) ;; Ensure we trigger the shut down of all remaining rings. (! x (tuple 'pass (ring-col x xs) msg))) ;; We've received a message, pass it on to the next ring. ((tuple 'pass (cons x xs) msg) - (: io format '"Recieved Message~n" '()) + (io:format "Recieved Message~n" '()) (! x (tuple 'pass (ring-col x xs) (+ msg 1))) ;; Make sure we're still around to receive the next one. (ring n-msgs))))) @@ -167,7 +168,7 @@ ;; until the list is exhausted. (() 'done) ;; No more stars, we're done here. ((cons x xs) - (: io format '"Sent message to star~n" '()) + (io:format "Sent message to star~n" '()) (! x (tuple 'msg (self))) (receive ;; Wait until the star replies before moving on to the next one. ;; Recur into the rest of the list. @@ -176,18 +177,18 @@ (defun start_star ;; Start our star communication process ((n-stars n-msgs) (when (is_number n-stars) (is_number n-msgs)) ;; Use the function from earlier to create our list of pids - (let* (stars (create-pids-one-arg 'star n-stars (: lists seq 1 n-stars))) + (let* (stars (create-pids-one-arg 'star n-stars (lists:seq 1 n-stars))) ;; For every message, trigger a sequence of communication with every ;; star. This is inside the let* so I can deliberately discard the ;; value and not be yelled at by the compiler. - (_ (lc ((<- _ (: lists seq 1 n-msgs))) (contact_stars stars))) + (_ (lc ((<- _ (lists:seq 1 n-msgs))) (contact_stars stars))) ;; Ensure all the star processes are killed off. (lc ((<- star stars)) (! star 'die))))) (defun star (x) ;; Our star receiver function (receive ((tuple 'msg from) ;; Received a message from the core. - (: io format '"Received msg from center~n" '()) + (io:format "Received msg from center~n" '()) (! from 'ok) (star x)) ('die 'ok))) ;; Received instruction to die from the core.
View file
_service:tar_scm:lfe-1.3.tar.gz/get_comp_opts.escript -> _service:tar_scm:lfe-2.1.1.tar.gz/get_comp_opts.escript
Changed
@@ -3,36 +3,15 @@ %% Define a number of compiler options. We first work out the current %% Erlang version and from the we can define the various options. -%% Bloody useful. --define(IF(Test,True,False), case Test of true -> True; false -> False end). - -%% Define the makefile variables HAS_MAPS and HAS_FULL_KEYS depending -%% on whether this version of erlang has maps (17) and general map -%% keys (18), or NEW_CORE_REC for new core definition of records (19). - --define(HAS_MAPS_OPT, "-DHAS_MAPS=true"). --define(FULL_KEYS_OPT, "-DHAS_FULL_KEYS=true"). --define(NEW_REC_OPT, "-DNEW_REC_CORE=true"). --define(NEW_RAND_OPT, "-DNEW_RAND=true"). +%% Define the makefile variables HAS_MAPS, HAS_FULL_KEYS, +%% NEW_REC_CORE, NEW_RAND, HAS_FLOOR, HAS_CEIL and NEW_STACKTRACE +%% depending on version of Erlang. main(_) -> Version = otp_release(), CompOpts = comp_opts(Version), file:write_file("comp_opts.mk", "COMP_OPTS = " ++ CompOpts ++ "\n"). -comp_opts(Version) -> - Copts0 = "-DERLANG_VERSION=\\\"" ++ Version ++ "\\\"", - Copts1 = ?IF(Version >= "17", Copts0 ++ " " ++ ?HAS_MAPS_OPT, Copts0), - Copts2 = ?IF(Version >= "18", Copts1 ++ " " ++ ?FULL_KEYS_OPT, Copts1), - Copts3 = ?IF(Version >= "19", - Copts2 ++ append_copts(?NEW_REC_OPT,?NEW_RAND_OPT), - Copts2), - Copts3. - -append_copts(Copt|Copts) -> - " " ++ Copt ++ append_copts(Copts); -append_copts() -> . - %% Get the release number. %% We have stolen the idea and most of the code from rebar3. @@ -60,3 +39,23 @@ end end end. + +comp_opts(Version) -> + Copts0 = "-DERLANG_VERSION=\\\"" ++ Version ++ "\\\"" ++ " ", + Copts0 ++ append_copts(Version, {"17","HAS_MAPS"}, + {"18","HAS_FULL_KEYS"}, + {"19","NEW_REC_CORE"}, + {"19","NEW_RAND"}, + {"20","NEW_BOOL_GUARD"}, + {"20","HAS_FLOOR"}, + {"20","HAS_CEIL"}, + {"21","NEW_STACKTRACE"}, + {"23","EEP48"}). + +append_copts(Version, {Ver,Opt}|Opts) -> + Rest = append_copts(Version, Opts), + if Version >= Ver -> + "-D" ++ Opt ++ "=true" ++ " " ++ Rest; + true -> Rest + end; +append_copts(_Version, ) -> .
View file
_service:tar_scm:lfe-1.3.tar.gz/include/clj.lfe -> _service:tar_scm:lfe-2.1.1.tar.gz/include/clj.lfe
Changed
@@ -17,6 +17,8 @@ ;;; Conditional macros. +(defmacro if-let args `(clj:if-let ,@args)) +(defmacro iff-let args `(clj:iff-let ,@args)) (defmacro condp args `(clj:condp ,@args)) (defmacro if-not args `(clj:if-not ,@args)) (defmacro iff args `(clj:iff ,@args))
View file
_service:tar_scm:lfe-1.3.tar.gz/include/match-spec.lfe -> _service:tar_scm:lfe-2.1.1.tar.gz/include/match-spec.lfe
Changed
@@ -1,4 +1,4 @@ -;; Copyright (c) 2008-2013 Robert Virding +;; Copyright (c) 2008-2020 Robert Virding ;; ;; Licensed under the Apache License, Version 2.0 (the "License"); ;; you may not use this file except in compliance with the License.
View file
_service:tar_scm:lfe-2.1.1.tar.gz/include/scm.lfe
Added
@@ -0,0 +1,23 @@ +;; Copyright (c) 2020 Robert Virding +;; +;; Licensed under the Apache License, Version 2.0 (the "License"); +;; you may not use this file except in compliance with the License. +;; You may obtain a copy of the License at +;; +;; http://www.apache.org/licenses/LICENSE-2.0 +;; +;; Unless required by applicable law or agreed to in writing, software +;; distributed under the License is distributed on an "AS IS" BASIS, +;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +;; See the License for the specific language governing permissions and +;; limitations under the License. + +;; File : scm.erl +;; Author : Robert Virding +;; Purpose : Lisp Flavoured Erlang scheme include macros + +(defmacro begin args `(scm:begin ,@args)) +(defmacro define args `(scm:define ,@args)) +(defmacro define-syntax args `(scm:define-syntax ,@args)) +(defmacro let-syntax args `(scm:let-syntax ,@args)) +(defmacro defsyntax args `(scm:defsyntax ,@args))
View file
_service:tar_scm:lfe-1.3.tar.gz/rebar.config -> _service:tar_scm:lfe-2.1.1.tar.gz/rebar.config
Changed
@@ -2,20 +2,37 @@ {erl_opts, debug_info}. -{profiles, {test, {deps, proper}}}. +%% IMPORTANT! Versions of proper are calculated dynamically in the 'rebar.config.script' file, at the end; +%% DO NOT set/change the proper version here! +{profiles, {test, {deps, proper}, + {plugins, {rebar3_proper, {git, "https://github.com/ferd/rebar3_proper", {tag, "0.12.1"}}}}, + {src_dirs, "src", "test"}}, + {dialyzer, }}. + +%% XXX Commenting this out due to weird recursion issues with rebar3_lfe ... +%% Do we remember why we need this? I _thought_ it was to help with +%% publishing LFE to hex.pm; once we remember, we should add a code +%% for future reference. +%% This issue is tracked here: +%% * https://github.com/lfe/lfe/issues/461 +%% Long term solution being tracked here: +%% * https://github.com/lfe/lfe/issues/460 +%% {plugins, +%% {rebar3_lfe, "0.3.1"} +%% }. {pre_hooks, {"(linux|darwin|solaris|freebsd|netbsd|openbsd)", ct, - "bin/lfe bin/lfec" + "bin/lfescript bin/lfec" " -o $REBAR_DEPS_DIR/lfe/test" " test/*_SUITE.lfe"}, {"(linux|darwin|solaris|freebsd|netbsd|openbsd)", eunit, - "bin/lfe bin/lfec" + "bin/lfescript bin/lfec" " -o $REBAR_DEPS_DIR/lfe/ebin" - " test/clj-tests.lfe"}, + " test/clj-tests.lfe test/maps-tests.lfe"}, %% TODO: Test this on a win32 box %% {"win32", ct, - %% "bin/lfe bin/lfec -o $REBAR_DEPS_DIR/lfe/test test/*_SUITE.lfe"} + %% "bin/lfescript bin/lfec -o $REBAR_DEPS_DIR/lfe/test test/*_SUITE.lfe"} {"(linux|darwin|solaris|freebsd|netbsd|openbsd)", app_compile, - "bin/lfe bin/lfec -o $REBAR_DEPS_DIR/lfe/ebin src/*.lfe"} + "bin/lfescript bin/lfec -o $REBAR_DEPS_DIR/lfe/ebin src/*.lfe"} %% TODO: equivalent win32 hook }.
View file
_service:tar_scm:lfe-1.3.tar.gz/rebar.config.script -> _service:tar_scm:lfe-2.1.1.tar.gz/rebar.config.script
Changed
@@ -1,56 +1,99 @@ %% -*- mode: erlang; indent-tabs-mode: nil -*- -Conf0 = CONFIG, -HasOpt = {d,'HAS_MAPS',true}, -FullOpt = {d,'HAS_FULL_KEYS',true}, -RecOpt = {d,'NEW_REC_CORE',true}, -RandOpt = {d,'NEW_RAND',true}, +Conf0 = CONFIG, %The original config -%% Get the release number. -%% We have stolen the idea and most of the code from rebar3. +%% Do a deep set stepping down a list of keys replacing/adding last +%% with value. Named funs would be nicer but not always available. -Version = case erlang:system_info(otp_release) of - $R,N1|Rest when is_integer(N1) -> - %% If OTP <= R16, take the digits. - N1|Rest; - Rel -> - File = filename:join(code:root_dir(),"releases",Rel,"OTP_VERSION"), - case file:read_file(File) of - {error, _} -> Rel; - {ok, Vsn} -> - Size = byte_size(Vsn), - %% The shortest vsn string consists of at least - %% two digits followed by "\n". Therefore, it's - %% safe to assume Size >= 3. - case binary:part(Vsn, {Size, -3}) of - <<"**\n">> -> - binary:bin_to_list(Vsn, {0, Size - 3}); - _ -> - binary:bin_to_list(Vsn, {0, Size - 1}) - end +SetConf = fun (K, Val, Ps, _F) -> + %% Replace the whole K field with Val. + Val|proplists:delete(K, Ps); + (K|Ks, Val, Ps, F) -> + %% Step down and build coming up. + case lists:keyfind(K, 1, Ps) of + {K,Kps} -> + lists:keyreplace(K, 1, Ps, {K,F(Ks, Val, Kps, F)}); + false -> Ps ++ {K,F(Ks, Val, , F)} end end, -%% These are the macros we add to the configuration. +%% Get the release number. +%% We have stolen the idea and most of the code from rebar3. + +OTPRelease = + fun () -> + case erlang:system_info(otp_release) of + $R,N1|Rest when is_integer(N1) -> + %% If OTP <= R16, take the digits. + N1|Rest; + Rel -> + File = filename:join(code:root_dir(),"releases",Rel,"OTP_VERSION"), + case file:read_file(File) of + {error, _} -> Rel; + {ok, Vsn} -> + Size = byte_size(Vsn), + %% The shortest vsn string consists of at least + %% two digits followed by "\n". Therefore, it's + %% safe to assume Size >= 3. + case binary:part(Vsn, {Size, -3}) of + <<"**\n">> -> + binary:bin_to_list(Vsn, {0, Size - 3}); + _ -> + binary:bin_to_list(Vsn, {0, Size - 1}) + end + end + end + end, + +Version = OTPRelease(), + +%% Collect the macro definitions we will add to the compiler options. +%% Named funs would be nicer but not always available. + +AppendCopts = fun (Version, {Ver,Opt}|Opts, F) -> + Rest = F(Version, Opts, F), + if Version >= Ver -> + {d,Opt,true}|Rest; + true -> + Rest + end; + (_Version, , _F) -> + end, Copts0 = {d,'ERLANG_VERSION',Version}, -Copts1 = if Version >= "17" -> Copts0 ++ HasOpt; - true -> Copts0 - end, -Copts2 = if Version >= "18" -> Copts1 ++ FullOpt; - true -> Copts1 - end, -Copts3 = if Version >= "19" -> Copts2 ++ RecOpt,RandOpt; - true -> Copts2 - end, -Copts = Copts3, %This is it - -%% Now add them. - -case lists:keyfind(erl_opts, 1, Conf0) of - {erl_opts,Opts} -> %Existing erl_opts - NewOpts = {erl_opts,Opts ++ Copts}, - lists:keyreplace(erl_opts, 1, Conf0, NewOpts); - false -> %No erl_opts - Conf0 ++ {erl_opts,Copts} -end. +Copts = Copts0 ++ AppendCopts(Version, + {"17",'HAS_MAPS'}, + {"18",'HAS_FULL_KEYS'}, + {"19",'NEW_REC_CORE'}, + {"19",'NEW_RAND'}, + {"20",'NEW_BOOL_GUARD'}, + {"20",'HAS_FLOOR'}, + {"20",'HAS_CEIL'}, + {"21",'NEW_STACKTRACE'}, + {"23",'EEP48'}, + AppendCopts), + +%% Ensure they are in erl_opts. + +Conf1 = case lists:keyfind(erl_opts, 1, Conf0) of + {erl_opts,Opts} -> %Existing erl_opts + NewOpts = {erl_opts,Opts ++ Copts}, + lists:keyreplace(erl_opts, 1, Conf0, NewOpts); + false -> %No erl_opts + Conf0 ++ {erl_opts,Copts} + end, + +%% Get the proper dep we will add to profiles-test-deps. + +Prop = if + Version =< "17" -> {proper, "1.1.1-beta"}; + Version =< "21" -> {proper, "1.3.0"}; + Version =< "23" -> {proper, "1.4.0"}; + true -> proper + end, + +%% Ensure we have set the right value of proper dep. + +Conf2 = SetConf(profiles,test,deps,proper, Prop, Conf1, SetConf), + +Conf2.
View file
_service:tar_scm:lfe-1.3.tar.gz/src/NOTES -> _service:tar_scm:lfe-2.1.1.tar.gz/src/NOTES
Changed
@@ -1,4 +1,4 @@ - Copyright (c) 2013 Robert Virding + Copyright (c) 2013-2020 Robert Virding Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.
View file
_service:tar_scm:lfe-1.3.tar.gz/src/cl.lfe -> _service:tar_scm:lfe-2.1.1.tar.gz/src/cl.lfe
Changed
@@ -1,4 +1,4 @@ -;; Copyright (c) 2015-2016 Robert Virding +;; Copyright (c) 2015-2020 Robert Virding ;; ;; Licensed under the Apache License, Version 2.0 (the "License"); ;; you may not use this file except in compliance with the License. @@ -48,7 +48,9 @@ (acons 3) (pairlis 2) (pairlis 3) (assoc 2) (assoc-if 2) (assoc-if-not 2) (rassoc 2) (rassoc-if 2) (rassoc-if-not 2) ;; Types. - (type-of 1) (coerce 2)) + (type-of 1) (coerce 2) + ;; System + (posix-argv 0)) (export-macro ;; Export control structure macros. do @@ -74,16 +76,16 @@ (defmacro do args "vars (end-test result) body" (let* ((`(,pars (,test ,ret) . ,body) args) - ((tuple vs is cs) - (lists:foldr (match-lambda - ((list v i c) (tuple vs is cs) - (tuple (cons v vs) (cons i is) (cons c cs)))) - (tuple () () ()) pars))) + ((tuple vs is cs) + (lists:foldr (match-lambda + ((list v i c) (tuple vs is cs) + (tuple (cons v vs) (cons i is) (cons c cs)))) + (tuple () () ()) pars))) `(letrec-function ((|\|-do-func-\|| - (lambda ,vs - (if ,test ,ret - (let ((do-state (progn . ,body))) - (|\|-do-func-\|| . ,cs)))))) + (lambda ,vs + (if ,test ,ret + (let ((do-state (progn . ,body))) + (|\|-do-func-\|| . ,cs)))))) (|\|-do-func-\|| . ,is)))) (defun mapcar (func list) @@ -234,7 +236,7 @@ (defun length (seq (when (is_list seq)) - (length seq)) + (erlang:length seq)) ;To ensure we call system length (seq (when (is_tuple seq)) (tuple_size seq))) @@ -683,7 +685,7 @@ (cond ((io_lib:printable_latin1_list x) 'string) ((io_lib:printable_unicode_list x) 'unicode) ((?= `(,a . ,b) (when (not (is_list b))) x) 'cons) - ('true 'list))) + (else 'list))) ((x) (when (is_function x)) 'function) ((x) (when (is_binary x))
View file
_service:tar_scm:lfe-1.3.tar.gz/src/clj.lfe -> _service:tar_scm:lfe-2.1.1.tar.gz/src/clj.lfe
Changed
@@ -1,4 +1,4 @@ -;; Copyright (c) 2015-2016 Robert Virding +;; Copyright (c) 2015-2020 Robert Virding ;; ;; Licensed under the Apache License, Version 2.0 (the "License"); ;; you may not use this file except in compliance with the License. @@ -59,7 +59,8 @@ `(defun ,@args)) (defmacro fn args - "Equivalent to `lambda`." + "args + Equivalent to `lambda`." `(lambda ,@args)) ;;; Threading macros. @@ -184,7 +185,8 @@ (some->>* args)) (defmacro doto - "Evaluate all given `sexps` and functions in order, + "x . sexps + Evaluate all given `sexps` and functions in order, for their side effects, with the value of `x` as the first argument and return `x`." (`(,x . ,sexps) @@ -207,7 +209,8 @@ `(case ,test ('false ,else) ('undefined ,else) - (,patt ,then)))) + (,patt ,then) + (_ ,else)))) (case args ((list (list patt test) then) (exp-if-let patt test then `'undefined)) ((list (list patt test) then else) (exp-if-let patt test then else))))) @@ -221,7 +224,8 @@ `(case ,test ('false 'undefined) ('undefined 'undefined) - (,patt ,@body)))) + (,patt ,@body) + (_ 'undefined)))) (defmacro condp args "pred expr . clauses @@ -278,7 +282,8 @@ (_ 'undefined)))) (defmacro not= - "Same as `(not (== ...))`." + "exp + Same as `(not (== ...))`." (`(,x) `'false) (`(,x ,y . ,more) `(not (== ,x ,y ,@more)))) @@ -344,7 +349,8 @@ N.B. `record?/2` may yield unexpected results, due to difference between the Erlang and LFE compilers. As such, whenever possible, prefer `record?/3`." ;; NOTE: record-tag must be an atom - (`(,x ,record-tag) `(is_record ,x ,record-tag)) + (`(,x ,record-tag) `(andalso (is_tuple ,x) + (=:= (tref ,x 1) ,record-tag))) (`(,x ,record-tag ,size) `(is_record ,x ,record-tag ,size))) (defmacro reference? (x) @@ -389,7 +395,7 @@ (defmacro even? (x) "Return `'true` if `x` is even." - `(clj:zero? ,(band 1 x))) + `(clj:zero? (band 1 ,x))) (defmacro zero? (x) "Return `'true` if `x` is zero." @@ -574,7 +580,7 @@ (sets:is_element elem data)) ((ordsets:is_set data) (ordsets:is_element elem data)) - ('true 'false)))) + (else 'false)))) ;;; Sequence functions. @@ -777,7 +783,7 @@ ((dict? data) (-get-in-dict data keys not-found)) ((list? data) (-get-in-list data keys not-found)) ((map? data) (-get-in-map data keys not-found)) - ('true not-found)))) + (else not-found)))) (defn- -get-in (func data `(,key) not-found
View file
_service:tar_scm:lfe-1.3.tar.gz/src/lfe.app.src -> _service:tar_scm:lfe-2.1.1.tar.gz/src/lfe.app.src
Changed
@@ -1,5 +1,5 @@ -%% -*- erlang -*- -%% Copyright (c) 2013-2016 Robert Virding +%% -*- mode: erlang; indent-tabs-mode: nil -*- +%% Copyright (c) 2013-2021 Robert Virding %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -15,19 +15,23 @@ {application, lfe, {description, "Lisp Flavored Erlang (LFE)"}, - {vsn, "1.3"}, - {modules,cl,clj,lfe,lfe_bits,lfe_codegen,lfe_comp,lfe_doc, - lfe_edlin_expand,lfe_env,lfe_eval,lfe_gen,lfe_init,lfe_io, - lfe_io_format,lfe_io_pretty,lfe_io_write,lfe_lib, - lfe_lint,lfe_macro,lfe_macro_export,lfe_macro_include, - lfe_macro_record,lfe_ms,lfe_parse,lfe_pmod,lfe_qlc, - lfe_scan,lfe_shell,lfe_trans,lfescript}, + {vsn, "2.1.1"}, + {modules,cl,clj,lfe,lfe_abstract_code,lfe_bits,lfe_codegen, + lfe_codelift,lfe_comp,lfe_docs,lfe_edlin_expand, + lfe_env,lfe_eval,lfe_eval_bits,lfe_gen,lfe_init, + lfe_internal,lfe_io,lfe_io_format,lfe_io_pretty, + lfe_io_write,lfe_lib,lfe_lint,lfe_macro, + lfe_macro_export,lfe_macro_include,lfe_macro_record, + lfe_macro_struct,lfe_ms,lfe_parse,lfe_qlc,lfe_scan, + lfe_shell,lfe_shell_docs,lfe_struct,lfe_translate, + lfe_types,lfescript,scm}, {registered, }, {applications, kernel,stdlib,compiler}, {maintainers, "Robert Virding"}, {licenses, "Apache"}, - {links, {"Github", "https://github.com/rvirding/lfe"}, - {"Main site", "http://lfe.io/"}, - {"Documentation", "http://docs.lfe.io/"}}, - {files, "src", "include", "bin", "rebar.*", "README.md", "LICENSE"} + {links, {"Github", "https://github.com/lfe/lfe"}, + {"Main site", "https://lfe.io/"}, + {"Documentation", "https://lfe.io/use/#reference"}}, + {files, "README.md", "LICENSE", "src", "c_src", "include", "bin", + "rebar.*", "*akefile", "*.escript"} }.
View file
_service:tar_scm:lfe-1.3.tar.gz/src/lfe.erl -> _service:tar_scm:lfe-2.1.1.tar.gz/src/lfe.erl
Changed
@@ -1,4 +1,4 @@ -%% Copyright (c) 2016 Robert Virding +%% Copyright (c) 2016-2020 Robert Virding %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License.
View file
_service:tar_scm:lfe-1.3.tar.gz/src/lfe.hrl -> _service:tar_scm:lfe-2.1.1.tar.gz/src/lfe.hrl
Changed
@@ -1,4 +1,4 @@ -%% Copyright (c) 2014-2015 Robert Virding +%% Copyright (c) 2014-2020 Robert Virding %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -21,3 +21,22 @@ -define(BQ(E), backquote,E). -define(C(E), comma,E). -define(C_A(E), 'comma-at',E). + +%% Some commonly used macros. + +%% Define IS_MAP/1 macro for is_map/1 bif. +-ifdef(HAS_MAPS). +-define(IS_MAP(T), is_map(T)). +-else. +-define(IS_MAP(T), false). +-endif. + +%% Define CATCH to handle deprecated get_stacktrace/0 +-ifdef(NEW_STACKTRACE). +-define(CATCH(C, E, S), C:E:S ->). +-else. +-define(CATCH(C, E, S), C:E -> S = erlang:get_stacktrace(),). +-endif. + +%% Bloody useful +-define(IF(Test,True,False), case Test of true -> True; false -> False end).
View file
_service:tar_scm:lfe-2.1.1.tar.gz/src/lfe_abstract_code.erl
Added
@@ -0,0 +1,50 @@ +%% Copyright (c) 2017-2020 Robert Virding +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. + +%%% File : lfe_abstract_code.erl +%%% Author : Robert Virding +%%% Purpose : Extract LFE abstract code for BEAM data. + +%% This has been copied from erl_abstract_code.erl. + +-module(lfe_abstract_code). +-export(debug_info/4). + +%% debug_info(Format, Module, Data, Options) -> {ok,Code} | {error,Error}. + +debug_info(_Format, _Module, {none,_Copts}, _Opts) -> + {error, missing}; +debug_info(erlang_v1, _Mod, {AbstrCode,_CompilerOpts}, _Opts) -> + {ok,AbstrCode}; +debug_info(core_v1, _Mod, {AbstrCode,CompilerOpts}, Opts) -> + CoreOpts = add_core_returns(delete_reports(CompilerOpts ++ Opts)), + try compile:noenv_forms(AbstrCode, CoreOpts) of + {ok,_,Core,_} -> {ok,Core}; + _Error -> {error,failed_conversion} + catch + error:_E -> {error,failed_conversion} + end; +debug_info(_Format, _, _Data, _) -> + {error,unknown_format}. + +delete_reports(Opts) -> + Opt || Opt <- Opts, not is_report_option(Opt). + +is_report_option(report) -> true; +is_report_option(report_errors) -> true; +is_report_option(report_warnings) -> true; +is_report_option(_) -> false. + +add_core_returns(Opts) -> + to_core,return_errors,return_warnings ++ Opts.
View file
_service:tar_scm:lfe-1.3.tar.gz/src/lfe_bits.erl -> _service:tar_scm:lfe-2.1.1.tar.gz/src/lfe_bits.erl
Changed
@@ -1,4 +1,4 @@ -%% Copyright (c) 2011-2013 Robert Virding +%% Copyright (c) 2011-2020 Robert Virding %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License.
View file
_service:tar_scm:lfe-1.3.tar.gz/src/lfe_codegen.erl -> _service:tar_scm:lfe-2.1.1.tar.gz/src/lfe_codegen.erl
Changed
@@ -1,4 +1,4 @@ -%% Copyright (c) 2008-2017 Robert Virding +%% Copyright (c) 2008-2020 Robert Virding %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -14,1719 +14,385 @@ %%% File : lfe_codegen.erl %%% Author : Robert Virding -%%% Purpose : Lisp Flavoured Erlang code generator (to core Erlang). - -%%% We have to be very careful to generate annotations in exactly the -%%% same way as the erlang compiler does and in the same places. -%%% Dialyzer is very finnicky about this and seriously fails if things -%%% are not as it expects them to be. Note that now the whole -%%% annotation is passed into the constructor functions, not just the -%%% line number. +%%% Purpose : Lisp Flavoured Erlang code generator (to Erlang AST). + +%%% We must be careful to generate code in the right order so as not +%%% to generate something the Erlang AST compiler won't find errors +%%% that are due to ordering but don't really exist. We first collect +%%% and generate all the "real" attributes from the module forms which +%%% must be first but we keep type/spec/record declarations in the +%%% same relative place as in the original file. %%% -%%% We make temporary variables of the form ' <num> ', which while -%%% they are not guaranteed to be unique are pretty unlikely. +%%% Note that for (export all) we only export the top-level functions +%%% defined in the module, not any of the lambda lifted functions. +%%% This means that we cannot generate "-compile(export_all)." but +%%% must explicitly export the functions. +%%% +%%% Having import from and rename forces us to explicitly convert the +%%% call as we can't use an import attribute to do this properly for +%%% us. Hence we collect the imports here and pass them into +%%% lfe_translate. +%%% +%%% Module aliases are also collected here and passed on to +%%% lfe_translate. -module(lfe_codegen). --export(module/2). - --compile(export_all). +-export(module/2,format_error/1). --import(lists, member/2,keysearch/3,reverse/1, - all/2,map/2,foldl/3,foldr/3,mapfoldl/3,mapfoldr/3, - concat/1,zipwith/3). --import(ordsets, add_element/2,is_element/2,from_list/1,union/2). --import(orddict, store/3,find/2). - --import(lfe_env, new/0,add_env/2, - add_vbinding/3,get_vbinding/2,add_fbinding/4, - add_ibinding/5,get_gbinding/3). +%% -compile(export_all). +-include("lfe.hrl"). -include("lfe_comp.hrl"). -%% Define IS_MAP/1 macro for is_map/1 bif. --ifdef(HAS_MAPS). --define(IS_MAP(T), is_map(T)). --else. --define(IS_MAP(T), false). --endif. - --define(Q(E), quote,E). %We do a lot of quoting! - --record(cg, {module=, %Module name - exps=, %Exports (ordsets) - imps=, %Imports (orddict) - pref=, %Prefixes - atts=, %Attrubutes - mets=, %Metadata - defs=, %Function definitions. - env=, %Environment - anno=, %Current annotation - opts=, %Options - file=, %File name - func=, %Current function - line=0, %Current line - vc=0, %Variable counter - fc=0 %Function counter +-record(lfe_cg, {module=, %Module name + mline=0, %Module definition line + exports=ordsets:new(), %Exports + imports=orddict:new(), %Imports + aliases=orddict:new(), %Aliases + onload=, %Onload + atts=, %Attrubutes + defs=, %Defined top-level functions + opts=, %Options + file=, %File name + func=, %Current function + errors=, %Errors + warnings= %Warnings }). -%% module(ModuleForms, CompInfo) -> {ModuleName,CoreModule} +%% Errors. +format_error({illegal_code,Code}) -> + lfe_io:format1(<<"illegal ~w code">>, Code). + +%% module(ModuleForms, CompInfo) -> +%% {ok,ModuleName,ASTModule,Warning} | {error,Error,Warning}. module(Mfs, #cinfo{opts=Opts,file=File}) -> - St0 = #cg{opts=Opts,file=File}, - {Core,St1} = compile_module(Mfs, St0), - {St1#cg.module,Core}. + St0 = #lfe_cg{opts=Opts,file=File}, + {AST,St1} = compile_module(Mfs, St0), + %% io:format("imps ~p\n", St1#lfe_cg.imports), + return_status(AST, St1). -%% compile_module(ModuleForms, State) -> {CoreModule,State}. +return_status(AST, #lfe_cg{module=M,errors=}=St) -> + {ok,M,AST,St#lfe_cg.warnings}; +return_status(_AST, St) -> + {error,St#lfe_cg.errors,St#lfe_cg.warnings}. compile_module(Mfs, St0) -> - {Fbs,St1} = collect_module(Mfs, St0), - Core = c_module(c_atom(none), , ), - compile_forms(Fbs, St1, Core). - -%% collect_module(ModuleForms, State) -> {Fbs,State}. -%% Collect forms and module data. Returns function bindings and puts -%% module data into state. - -collect_module(Mfs, St0) -> - {Fds,St1} = lists:foldl(fun collect_form/2, {,St0}, Mfs), - {lists:reverse(Fds),St1}. - -%% collect_form(Form, Line, State} -> {FuncDefs,State}. -%% Collect valid forms and module data. Returns forms and put module -%% data into state. - -collect_form({'define-module',Mod,Metas,Atts,L}, {Fds,St0}) -> - St1 = collect_metas(Metas, L, St0#cg{module=Mod,anno=L}), - {Fds,collect_attrs(Atts, L, St1)}; -collect_form({'extend-module',Meta,Atts,L}, {Fds,St0}) -> - St1 = collect_metas(Meta, L, St0#cg{anno=L}), - {Fds,collect_attrs(Atts, L, St1)}; -collect_form({'define-type',Type,Def,L}, {Fds,St}) -> - {Fds,collect_meta(type,Type,Def, L, St#cg{anno=L})}; -collect_form({'define-opaque-type',Type,Def,L}, {Fds,St}) -> - {Fds,collect_meta(opaque,Type,Def, L, St#cg{anno=L})}; -collect_form({'define-function-spec',Func,Spec,L}, {Fds,St}) -> - {Fds,collect_meta(spec,Func,Spec, L, St#cg{anno=L})}; -collect_form({'define-function',Name,_Meta,Def,L}, {Fds,St}) -> - %% Ignore the meta data. - {{Name,Def,L}|Fds,St}; -%% Ignore macro definitions and eval-when-compile forms. -collect_form({'define-macro'|_,_}, {Fds,St}) -> {Fds,St}; -collect_form({'eval-when-compile'|_,_}, {Fds,St}) -> {Fds,St}. - -%% collect_metas(Metas, Line, State) -> State. -%% Collect module metadata which is to be compiled. Only type -%% information is to be kept. - -collect_metas(Ms, L, St) -> - foldl(fun (M, S) -> collect_meta(M, L, S) end, St, Ms). - -collect_meta(type|Tds, L, #cg{mets=Ms}=St) -> - St#cg{mets=Ms ++ {type,Tds,L}}; -collect_meta(opaque|Tds, L, #cg{mets=Ms}=St) -> - St#cg{mets=Ms ++ {opaque,Tds,L}}; -collect_meta(spec|Sps, L, #cg{mets=Ms}=St) -> - St#cg{mets=Ms ++ {spec,Sps,L}}; -collect_meta(record|Rds, L, #cg{mets=Ms}=St) -> - St#cg{mets=Ms ++ {record,Rds,L}}; -collect_meta(_M, _L, St) -> St. %Ignore the rest - -%% collect_attrs(Attributes, Line, State) -> State. -%% Collect module attributes and fill in the #cg state record. Need -%% to ignore all eventual doc attributes. - -collect_attrs(As, L, St) -> - %% io:format("ca: ~p\n", As), - foldl(fun (A, S) -> collect_attr(A, L, S) end, St, As). - -collect_attr(export|Es, _, St) -> collect_exps(Es, St); -collect_attr(import|Is, _, St) -> collect_imps(Is, St); -collect_attr(doc|_, _, St) -> St; %Don't save doc attribute! -collect_attr(N|Vs, L, #cg{atts=As}=St) -> - St#cg{atts=As ++ {N,Vs,L}}. %Probably not many - -collect_exps(all, St) -> St#cg{exps=all}; %Propagate all -collect_exps(_, #cg{exps=all}=St) -> St; -collect_exps(Es, #cg{exps=Exps0}=St) -> - %% Add exports to export set. - Exps1 = foldl(fun (F,A, E) -> add_element({F,A}, E) end, - Exps0, Es), - St#cg{exps=Exps1}. -
View file
_service:tar_scm:lfe-2.1.1.tar.gz/src/lfe_codelift.erl
Added
@@ -0,0 +1,910 @@ +%% Copyright (c) 2008-2018 Robert Virding +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. + +%%% File : lfe_codelift.erl +%%% Author : Robert Virding +%%% Purpose : Lisp Flavoured Erlang lambda lifting local functions. + +%%% Lambda lift local functions to the top-level. We do this ourselves +%%% to have better control and to be able to do non-recursive +%%% functions in a better way. + +-module(lfe_codelift). + +-export(record/3,function/3). + +-export(comp_define/1). +-export(lift_func/2,lift_expr/3,ivars_expr/1). + +-export(test/1). + +%% We do a lot of quoting! +-define(Q(E), quote,E). +-define(BQ(E), backquote,E). +-define(C(E), comma,E). +-define(C_A(E), 'comma-at',E). + +-record(cl, {func=, %Current function + arity=0, + line=0, + vc=0, %Local variable index + fc=0 %Local function index + }). + +%% comp_define(DefForm) -> Funcs + +comp_define({Name,Def,Line}) -> + Fs = 'define-function',N,,D || {N,D,_} <- function(Name, Def, Line) , + progn|Fs. + +%% record(Name, Fields, Line) -> {RecDef,Functions}. +%% Lambda lift the record field definitions and return the lifted +%% fields and generated functions. + +record(Name, Fs, Line) -> + St0 = #cl{func=Name,arity=record,line=Line,vc=0,fc=0}, + {Lfs,Fncs,St1} = lift_rec_fields(Fs, , St0), + {Lfncs,,_} = lift_loop(Fncs, St1), + {Lfs,Lfncs}. + +%% function(Name, Def, Line) -> {Name,Def,Line}. +%% Lambda lift all the local functions and return a list of all +%% functions. + +function(Name, Def, Line) -> + Ar = func_arity(Def), + St = #cl{func=Name,arity=Ar,line=Line,vc=0,fc=0}, + %% Lambda lift the function. + Func = {Name,Def,Line}, + {Funcs,,_} = lift_loop(Func, St), + %% io:format("codelift ~p\n", {Func,Funcs}), + Funcs. + +%% lift_loop(Functions, State) -> {TopFuncs,LiftedFuncs,State}. +%% Repeatedly traverse Functions and LiftedFunctions until everything +%% has been lifted. Return all as TopFuncs. + +lift_loop(Funcs0, St0) -> + {Funcs1,Lds,St1} = lift_funcs(Funcs0, St0), + if Lds =:= -> + {Funcs1,,St1}; + true -> + {Lfuncs,Lds1,St2} = lift_loop(Lds, St1), + {Funcs1 ++ Lfuncs,Lds1,St2} + end. + +%% lift_func(Name, Definiton, State) -> {Functions,State}. +%% Lambda lift the local functions in an a function. Return a list of +%% the resulting functions. + +lift_func({Name,Def0,L}, St0) -> + {Def1,Lds,St1} = lift_expr(Def0, , St0), + {{Name,Def1,L},Lds,St1}. + +lift_funcs(Defs, St) -> + Fun = fun (Func0, {Funcs, Lds0, St0}) -> + {Func1,Lds,St1} = lift_func(Func0, St0), + {Func1|Funcs,Lds ++ Lds0,St1} + end, + lists:foldl(Fun, {,,St}, Defs). + +%% lift_expr(Expr, LocalDefs, State) -> {AST,LocalDefs,State}. +%% Lambda lift the local functions in an expression. + +%% Core data special forms. +lift_expr(?Q(E), Lds, St) -> {?Q(E),Lds,St}; +%% Record special forms. +lift_expr('record',Name|Args, Lds0, St0) -> + {Largs,Lds1,St1} = lift_rec_args(Args, Lds0, St0), + {'record',Name|Largs,Lds1,St1}; +%% make-record has been deprecated but we sill accept it for now. +lift_expr('make-record',Name|Args, Lds0, St0) -> + {Largs,Lds1,St1} = lift_rec_args(Args, Lds0, St0), + {'make-record',Name|Largs,Lds1,St1}; +lift_expr('is-record',E,Name, Lds0, St0) -> + {Le,Lds1,St1} = lift_expr(E, Lds0, St0), + {'is-record',Le,Name,Lds1,St1}; +lift_expr('record-index',_Name,_F=Ri, Lds, St) -> + {Ri,Lds,St}; +lift_expr('record-field',E,Name,F, Lds0, St0) -> + {Le,Lds1,St1} = lift_expr(E, Lds0, St0), + {'record-field',Le,Name,F,Lds1,St1}; +lift_expr('record-update',E,Name|Args, Lds0, St0) -> + {Le,Lds1,St1} = lift_expr(E, Lds0, St0), + {Largs,Lds2,St2} = lift_rec_args(Args, Lds1, St1), + {'record-update',Le,Name|Largs,Lds2,St2}; +%% Struct special forms. +lift_expr('struct',Name|Args, Lds0, St0) -> + {Largs,Lds1,St1} = lift_rec_args(Args, Lds0, St0), + {'struct',Name|Largs,Lds1,St1}; +lift_expr('is-struct',E, Lds0, St0) -> + {Le,Lds1,St1} = lift_expr(E, Lds0, St0), + {'is-struct',Le,Lds1,St1}; +lift_expr('is-struct',E,Name, Lds0, St0) -> + {Le,Lds1,St1} = lift_expr(E, Lds0, St0), + {'is-struct',Le,Name,Lds1,St1}; +lift_expr('struct-field',E, Name,F, Lds0, St0) -> + {Le,Lds1,St1} = lift_expr(E, Lds0, St0), + {'struct-field',Le,Name,F,Lds1,St1}; +lift_expr('struct-update',E,Name|Args, Lds0, St0) -> + {Le,Lds1,St1} = lift_expr(E, Lds0, St0), + {Largs,Lds2,St2} = lift_rec_args(Args, Lds1, St1), + {'struct-update',Le,Name|Largs,Lds2,St2}; +%% Function forms. +lift_expr(function,_,_=Func, Lds, St) -> + {Func,Lds,St}; +lift_expr(function,_,_,_=Func, Lds, St) -> + {Func,Lds,St}; +%% Core closure special forms. +lift_expr(lambda,Args|Body0, Lds0, St0) -> + {Body1,Lds1,St1} = lift_exprs(Body0, Lds0, St0), + {lambda,Args|Body1,Lds1,St1}; +lift_expr('match-lambda'|Cls0, Lds0, St0) -> + {Cls1,Lds1,St1} = lift_cls(Cls0, Lds0, St0), + {'match-lambda'|Cls1,Lds1,St1}; +lift_expr('let',Vbs|Body, Lds, St) -> + lift_let(Vbs, Body, Lds, St); +lift_expr('let-function',Fbs|Body, Lds, St) -> + lift_let_function(Fbs, Body, Lds, St); +lift_expr('letrec-function',Fbs|Body, Lds, St) -> + lift_letrec_function(Fbs, Body, Lds, St); +%% Core control special forms. +lift_expr(progn|Body0, Lds0, St0) -> + {Body1,Lds1,St1} = lift_exprs(Body0, Lds0, St0), + {progn|Body1,Lds1,St1}; +lift_expr('if'|Body0, Lds0, St0) -> + {Body1,Lds1,St1} = lift_exprs(Body0, Lds0, St0), + {'if'|Body1,Lds1,St1}; +lift_expr('case',Expr|Cls, Lds, St) -> + lift_case(Expr, Cls, Lds, St); +lift_expr('catch'|Body0, Lds0, St0) -> + {Body1,Lds1,St1} = lift_exprs(Body0, Lds0, St0), + {'catch'|Body1,Lds1,St1}; +lift_expr('try'|Try, Lds, St) -> + lift_try(Try, Lds, St); +lift_expr(funcall|Body0, Lds0, St0) -> + {Body1,Lds1,St1} = lift_exprs(Body0, Lds0, St0), + {funcall|Body1,Lds1,St1}; +%% List/binary comprehensions. +lift_expr('lc',Qs,E, Lds, St) -> + lift_comp('lc', Qs, E, Lds, St); +lift_expr('list-comp',Qs,E, Lds, St) -> + lift_comp('list-comp', Qs, E, Lds, St); +lift_expr('bc',Qs,E, Lds, St) -> + lift_comp('bc', Qs, E, Lds, St); +lift_expr('binary-comp',Qs,E, Lds, St) -> + lift_comp('binary-comp', Qs, E, Lds, St); +%% Finally the general cases. +lift_expr(call|Body0, Lds0, St0) -> + {Body1,Lds1,St1} = lift_exprs(Body0, Lds0, St0), + {call|Body1,Lds1,St1}; +lift_expr(Func|Args0, Lds0, St0) when is_atom(Func) -> + {Args1,Lds1,St1} = lift_exprs(Args0, Lds0, St0), + {Func|Args1,Lds1,St1}; +lift_expr(Lit, Lds, St) -> {Lit,Lds,St}. + +lift_exprs(Exprs, Lds, St) -> + Fun = fun (E0, {Es,Lds0,St0}) -> + {E1,Lds1,St1} = lift_expr(E0, Lds0, St0),
View file
_service:tar_scm:lfe-1.3.tar.gz/src/lfe_comp.erl -> _service:tar_scm:lfe-2.1.1.tar.gz/src/lfe_comp.erl
Changed
@@ -1,4 +1,4 @@ -%% Copyright (c) 2008-2016 Robert Virding +%% Copyright (c) 2008-2020 Robert Virding %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -34,8 +34,12 @@ -import(lists, member/2,keyfind/3,filter/2,foreach/2,all/2,any/2, map/2,flatmap/2,foldl/3,foldr/3,mapfoldl/3,mapfoldr/3). +-include("lfe.hrl"). -include("lfe_comp.hrl"). +%% Mightn't use all commands in do_passes yet. +-dialyzer({no_match,do_passes/2}). + %% The main compiler state. -record(comp, {base="", %Base name @@ -49,7 +53,8 @@ code=, %Code after last pass. return=, %What is returned Val | errors=, - warnings= + warnings=, + extra= %Pass specific options, plist }). %% default_options() -> Options. @@ -85,8 +90,7 @@ Ret = try internal(Input, Opts) catch - error:Reason -> - St = erlang:get_stacktrace(), + ?CATCH(error, Reason, St) {error,{Reason,St}} end, exit(Ret) @@ -114,10 +118,10 @@ end. do_forms(Fs0, Opts0) -> - Source = proplists:get_value(source, Opts0, "-no-file-"), + Source = lprop(source, Opts0, ""), Opts1 = lfe_comp_opts(Opts0), St0 = #comp{opts=binary|Opts1}, %Implicit binary option - St1 = filenames(Source, ".lfe", St0), + St1 = filenames(Source, "", St0), St2 = include_path(St1), %% Tag forms with a "line number", just use their index. {Fs1,_} = mapfoldl(fun (F, N) -> {{F,N},N+1} end, 1, Fs0), @@ -129,20 +133,29 @@ filenames(File, Suffix, St) -> %% Test for explicit outdir. - Odir = outdir(St#comp.opts), + Odir = outdir(St#comp.opts, "."), Ldir = filename:dirname(File), Base = filename:basename(File, Suffix), - Lfile = filename:join(Ldir, Base ++ Suffix), + Lfile = lfefile(Ldir, Base, Suffix), St#comp{base=Base, ldir=Ldir, lfile=Lfile, odir=Odir }. -outdir({outdir,Dir}|_) -> Dir; %Erlang way -outdir(outdir,Dir|_) -> Dir; %LFE way -outdir(_|Opts) -> outdir(Opts); -outdir() -> ".". +lfefile(".", Base, Suffix) -> Base ++ Suffix; +lfefile(Dir, Base, Suffix) -> + filename:join(Dir, Base ++ Suffix). + +outdir(Opts, Def) -> lprop(outdir, Opts, Def). + +%% lprop(Key, PropList, Default) -> Value. +%% Find Key, Val from PropList else Default. + +lprop(Key, {Key,Val}|_, _) -> Val; %Erlang way +lprop(Key, Key,Val|_, _) -> Val; %LFE way +lprop(Key, _|List, Def) -> lprop(Key, List, Def); +lprop(_, , Def) -> Def. %% include_path(State) -> State. %% Set the include path, we permit {i,Dir} and i,Dir. @@ -168,14 +181,15 @@ Fun = fun ('to-split') -> to_split; ('to-expmac') -> to_expmac; ('to-expand') -> to_expand; - ('to-exp') -> to_exp; %Backwards compatibility - ('to-pmod') -> to_pmod; ('to-lint') -> to_lint; ('no-docs') -> no_docs; + ('to-erlang') -> to_erlang; ('to-core0') -> to_core0; ('to-core') -> to_core; ('to-kernel') -> to_kernel; ('to-asm') -> to_asm; + ('to-ast') -> to_ast; %The output should be an AST + ('debug-info') -> debug_info; ('no-export-macros') -> no_export_macros; ('warnings-as-errors') -> warnings_as_errors; ('report-warnings') -> report_warnings; @@ -229,25 +243,25 @@ %% Now we expand and trim remaining macros. {do,fun do_expand_macros/1}, {when_flag,to_expand,{done,fun expand_pp/1}}, - {when_flag,to_exp,{done,fun expand_pp/1}}, %Backwards compatibility - {do,fun do_lfe_pmod/1}, - {when_flag,to_pmod,{done,fun pmod_pp/1}}, {do,fun do_lfe_lint/1}, {when_flag,to_lint,{done,fun lint_pp/1}}, {unless_flag,no_docs,{do,fun do_get_docs/1}}, {do,fun do_lfe_codegen/1}, - {when_flag,to_core0,{done,fun core_pp/1}}, + {when_flag,to_erlang,{done,fun erlang_pp/1}}, {do,fun do_erl_comp/1}, %% These options will have made erlang compiler return internal %% form after pass. + {when_flag,to_core0,{done,fun erl_core_pp/1}}, {when_flag,to_core,{done,fun erl_core_pp/1}}, {when_flag,to_kernel,{done,fun erl_kernel_pp/1}}, {when_flag,to_asm,{done,fun erl_asm_pp/1}}, - %% Write docs beam chunks. - {unless_flag,no_docs,{do,fun do_add_docs/1}}, + %% Stop at non-binary returns, either return or drop. + {unless_test,fun is_binary_module/1,done}, %% Now we just write the beam file unless warnings-as-errors is %% set and we have warnings. {when_test,fun is_werror/1,error}, + %% Write docs beam chunks. + {do,fun add_chunks/1}, {done,fun beam_write/1} %Should be last . @@ -280,8 +294,11 @@ %% top-level macros in forms so we can safelt detect the start of %% each module (with define-module form). -do_split_file(#comp{cinfo=Ci,code=Code}=St) -> - case collect_pre_forms(Code, Ci) of %Expand pre module forms +do_split_file(#comp{lfile=Lfile,cinfo=Ci,code=Code0}=St) -> + %% Add a FILE macro with the file name at the beginning. + Mac = {defmacro,'FILE',,?BQ(?Q(Lfile)),1}, + Code1 = Mac|Code0, + case collect_pre_forms(Code1, Ci) of %Expand pre module forms {Pfs,Fs,Env0,Mst0} -> %% Expand the modules using the pre forms and environment. case collect_modules(Fs, Pfs, Env0, Mst0) of @@ -305,53 +322,53 @@ collect_pre_forms(Fs, Ci) -> Env = lfe_env:new(), %% Don't deep expand, keep everything. - St = lfe_macro:expand_form_init(Ci, false, true), - collect_mod_forms(Fs, Env, St). + Mst = lfe_macro:expand_form_init(Ci, false, true), + collect_mod_forms(Fs, Env, Mst). -%% collect_modules(Forms, PreForms, PreEnv, State) -> -%% {Modules,State}. +%% collect_modules(Forms, PreForms, PreEnv, MacroState) -> +%% {Modules,MacroState}. %% Collect and expand modules upto the end. Each module initially has %% the pre environment and all pre forms are appended to it. -collect_modules(Fs, PreFs, PreEnv, St) -> - collect_modules(Fs, , PreFs, PreEnv, St). +collect_modules(Fs, PreFs, PreEnv, Mst) -> + collect_modules(Fs, , PreFs, PreEnv, Mst). -collect_modules({'define-module',Name|_,_}=Mdef|Fs0, Ms, PreFs, PreEnv, St0) -> +collect_modules({'define-module',Name|_,_}=Mdef|Fs0, Ms, PreFs, PreEnv, Mst0) -> %% Expand and collect all forms upto next define-module or end. - case collect_mod_forms(Fs0, PreEnv, St0) of - {Mfs0,Fs1,_,St1} -> + case collect_mod_forms(Fs0, PreEnv, Mst0) of + {Mfs0,Fs1,_,Mst1} -> M = #module{name=Name,code=Mdef ++ PreFs ++ Mfs0}, - collect_modules(Fs1, M|Ms, PreFs, PreEnv, St1); + collect_modules(Fs1, M|Ms, PreFs, PreEnv, Mst1); Error -> Error end; -collect_modules(, Ms, _PreFs, _PreEnv, St) -> - {ok,lists:reverse(Ms),St}. +collect_modules(, Ms, _PreFs, _PreEnv, Mst) -> + {ok,lists:reverse(Ms),Mst}. -%% collect_mod_forms(Forms, Env, State) -> -%% collect_mod_forms(Forms, Acc, Env, State) -> -%% {Modforms,RestForms,Env,State}. +%% collect_mod_forms(Forms, Env, MacroState) -> +%% collect_mod_forms(Forms, Acc, Env, MacroState) -> +%% {Modforms,RestForms,Env,MacroState}. %% Expand and collect forms upto the next define-module or end. We %% also flatten top-level nested progn code. -collect_mod_forms(Fs, Env0, St0) ->
View file
_service:tar_scm:lfe-1.3.tar.gz/src/lfe_comp.hrl -> _service:tar_scm:lfe-2.1.1.tar.gz/src/lfe_comp.hrl
Changed
@@ -1,4 +1,4 @@ -%% Copyright (c) 2014-2015 Robert Virding +%% Copyright (c) 2014-2020 Robert Virding %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -26,20 +26,17 @@ -record(module, {name=, %Module name code=none, %Module code - warnings=, %Module warnings - docs= %Module docs + chunks=, %Extra chunks + warnings= %Module warnings }). -%% Bloody useful --define(IF(Test,True,False), case Test of true -> True; false -> False end). - %% ?WHEN_OPT(Option, Options, Fun) -> ok. %% ?UNLESS_OPT(Option, Options, Fun) -> ok. %% Call Fun when Option is/is not a member of Options. --define(WHEN_OPT(Opt,Opts,Fun), ?IF(member(Opt, Opts), Fun(), ok)). +-define(WHEN_OPT(Opt,Opts,Fun), ?IF(lists:member(Opt, Opts), Fun(), ok)). -%% -define(UNLESS_OPT(Opt,Opts,Fun), ?IF(member(Opt, Opts), ok, Fun())). +%% -define(UNLESS_OPT(Opt,Opts,Fun), ?IF(lists:member(Opt, Opts), ok, Fun())). -define(DEBUG(Format,Args,Opts), ?WHEN_OPT(debug_print, Opts,
View file
_service:tar_scm:lfe-2.1.1.tar.gz/src/lfe_docs.erl
Added
@@ -0,0 +1,279 @@ +%% Copyright (c) 2022 Robert Virding +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. + +%% File : lfe_docs.erl +%% Author : Robert Virding +%% Purpose : Lisp Flavoured Erlang documentation handling. + +%% This module takes a lot of input from an older module written by +%% Eric Bailey. +%% +%% The "Docs" format from EEP 48: Documentation storage and format +%% +%% {docs_v1, +%% Anno :: erl_anno:anno(), +%% BeamLanguage :: atom(), +%% Format :: mime_type(), +%% ModuleDoc :: #{DocLanguage := DocValue} | none | hidden, +%% Metadata :: map(), +%% Docs :: +%% {{Kind, Name, Arity}, +%% Anno :: erl_anno:anno(), +%% Signature :: binary(), +%% Doc :: #{DocLanguage := DocValue} | none | hidden, +%% Metadata :: map() +%% }} when DocLanguage :: binary(), +%% DocValue :: binary() | term() + +-module(lfe_docs). +-export(make_chunk/2,make_docs_info/2). + +-export(get_module_docs/1). + +-include("lfe_docs.hrl"). + +%% Internal lfe_doc records. +-record(docs, {copts=, + module=, + macs=, + funcs= + }). + +-record(module, {name=, %Name + anno=, %Annotations/line + docs=, %Documentation + meta=, %Metadata + atts=, %Attributes + fexps=, %Exported functions + mexps= %Exported macros + }). + +-record(function, {name=, %Name + arity=, %Arity + anno=, %Annotations/line + docs=, %Documentation + spec=none, %Spec + meta=, %Meta information + def= %Definition + }). + +-record(macro, {name=, %Name + arity=, %Arity, always 1 for macros + anno=, %Annotations/line + docs=, %Documentation + spec=none, %Spec + meta=, %Meta information + def= %Definition + }). + +make_chunk(Code, CompilerOpts) -> + {ok,DocInfo} = make_docs_info(Code, CompilerOpts), + Chunk = {"Docs",erlang:term_to_binary(DocInfo)}, + {ok,Chunk}. + +make_docs_info(Code, CompilerOpts) -> + DS0 = #docs{copts=CompilerOpts,module=#module{}}, + DS1 = collect_forms(Code, DS0), + #module{anno=Anno,docs=Mdocs} = DS1#docs.module, + Funcs = generate_functions(DS1), + Macros = generate_macros(DS1), + DocInfo = docs_v1(Anno, Mdocs, #{}, Funcs ++ Macros), + {ok,DocInfo}. + +%% collect_forms(Code, DocsState) -> DocsState. + +collect_forms(Code, DS) -> lists:foldl(fun collect_form/2, DS, Code). + +collect_form({'define-module',Name,Meta,Atts,Line}, #docs{module=M0}=DS) -> + M1 = M0#module{name=Name,anno=Line}, + M2 = collect_mod_attrs(Atts, M1), + M3 = collect_mod_metas(Meta, M2), + DS#docs{module=M3}; +collect_form({'extend-module',Meta,Atts,_Line}, #docs{module=M0}=DS) -> + M1 = collect_mod_attrs(Atts, M0), + M2 = collect_mod_metas(Meta, M1), + DS#docs{module=M2}; +collect_form({'define-function',Name,Meta,Def,Line}, #docs{funcs=Fs}=DS) -> + F = collect_function(Name, Meta, Def, Line), + DS#docs{funcs=Fs ++ F}; +collect_form({'define-macro',Name,Meta,Def,Line}, #docs{macs=Ms}=DS) -> + M = collect_macro(Name, Meta, Def, Line), + DS#docs{macs=Ms ++ M}; +collect_form(_, DS) -> DS. + +collect_mod_metas(Metas, Mod) -> + Collect = fun (doc|Ds, M) -> + M#module{docs=M#module.docs ++ Ds}; + (_, M) -> M + end, + lists:foldl(Collect, Mod, Metas). + +collect_mod_attrs(Attrs, Mod) -> + Collect = fun (doc|Ds, M) -> + M#module{docs=M#module.docs ++ Ds}; + (export|Es, #module{fexps=Fes}=M) -> + M#module{fexps=collect_mod_exports(Fes, Es)}; + ('export-macro'|Es, #module{mexps=Mes}=M) -> + M#module{mexps=collect_mod_exports(Mes, Es)}; + (_, M) -> M + end, + lists:foldl(Collect, Mod, Attrs). + +%% Must handle exporting all for functions and macros. +collect_mod_exports(_Exps, all) -> all; +collect_mod_exports(all, _Es) -> all; +collect_mod_exports(Exps, Es) -> Exps ++ Es. + +collect_function(Name, Meta, Def, Line) -> + F = #function{name=Name, + arity=function_arity(Def), + anno=Line, + meta=Meta, + def=Def}, + collect_fun_metas(Meta, F). + +collect_fun_metas(Metas, Fun) -> + Collect = fun (doc|Ds, F) -> + F#function{docs=F#function.docs ++ Ds}; + (spec|Ss, F) -> + F#function{spec=Ss}; + (_, F) -> F + end, + lists:foldl(Collect, Fun, Metas). + +function_arity(lambda,Args|_) -> length(Args); +function_arity('match-lambda',Pat|_|_) -> length(Pat). + +collect_macro(Name, Meta, Def, Line) -> + F = #macro{name=Name, + arity=1, %Default for all macros + anno=Line, + meta=Meta, + def=Def}, + collect_mac_metas(Meta, F). + +collect_mac_metas(Metas, Mac) -> + Collect = fun (doc|Ds, M) -> + M#macro{docs=M#macro.docs ++ Ds}; + (_, M) -> M + end, + lists:foldl(Collect, Mac, Metas). + +%% generate_functions(Docs) -> FunctionDoc. + +generate_functions(#docs{module=#module{fexps=Fexps},funcs=Funcs}) -> + Fdoc = fun (#function{name=Name,arity=Arity,anno=Anno,docs=Docs}=F) -> + Sig = generate_sig(F), + Spec = generate_spec(F), + docs_v1_entry(function, Name, Arity, Anno, Sig, Docs, Spec) + end, + Fdoc(F) || F <- Funcs, exported_function(F, Fexps). + +exported_function(_F, all) -> true; %All functions are exported. +exported_function(#function{name=N,arity=A}, Fexps) -> + lists:member(N,A, Fexps). + +%% generate_macros(Docs) -> MacroDoc. + +generate_macros(#docs{module=#module{mexps=Mexps},macs=Macros}) -> + Mdoc = fun (#macro{name=Name,arity=Arity,anno=Anno,docs=Docs}=M) -> + Sig = generate_sig(M), + Spec = generate_spec(M), + docs_v1_entry(macro, Name, Arity, Anno, Sig, Docs, Spec) + end, + Mdoc(M) || M <- Macros, exported_macro(M, Mexps) . + +exported_macro(_M, all) -> true; %All macros are exported. +exported_macro(#macro{name=N}, Mexps) -> + lists:member(N, Mexps).
View file
_service:tar_scm:lfe-2.1.1.tar.gz/src/lfe_docs.hrl
Added
@@ -0,0 +1,50 @@ +%% Copyright (c) 2020 Robert Virding +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. + +%% File : lfe_docs.hrl +%% Author : Robert Virding +%% Purpose : Common documentation-related definitions. + +%% The "Docs" format from EEP 48: Documentation storage and format +%% +%% {docs_v1, +%% Anno :: erl_anno:anno(), +%% BeamLanguage :: atom(), +%% Format :: mime_type(), +%% ModuleDoc :: #{DocLanguage := DocValue} | none | hidden, +%% Metadata :: map(), +%% Docs :: +%% {{Kind, Name, Arity}, +%% Anno :: erl_anno:anno(), +%% Signature :: binary(), +%% Doc :: #{DocLanguage := DocValue} | none | hidden, +%% Metadata :: map() +%% }} when DocLanguage :: binary(), +%% DocValue :: binary() | term() + +-define(NATIVE_FORMAT,<<"application/erlang+html">>). +-define(LFE_FORMAT, <<"text/markdown">>). + +-define(CURR_DOC_VERSION, {1,0,0}). + +%% The Docs v1 record. +-record(docs_v1, {anno, + beam_language, + format, + module_doc, + metadata, + docs = + }). + +-type docs_v1() :: #docs_v1{}.
View file
_service:tar_scm:lfe-1.3.tar.gz/src/lfe_edlin_expand.erl -> _service:tar_scm:lfe-2.1.1.tar.gz/src/lfe_edlin_expand.erl
Changed
@@ -1,21 +1,16 @@ +%% Copyright (c) 2008-2022 Robert Virding %% -%% %CopyrightBegin% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at %% -%% Copyright Ericsson AB 2005-2010. All Rights Reserved. -%% -%% The contents of this file are subject to the Erlang Public License, -%% Version 1.1, (the "License"); you may not use this file except in -%% compliance with the License. You should have received a copy of the -%% Erlang Public License along with this software. If not, it can be -%% retrieved online at http://www.erlang.org/. -%% -%% Software distributed under the License is distributed on an "AS IS" -%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See -%% the License for the specific language governing rights and limitations -%% under the License. -%% -%% %CopyrightEnd% +%% http://www.apache.org/licenses/LICENSE-2.0 %% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. -module(lfe_edlin_expand). @@ -39,9 +34,9 @@ case Bef1 of $:|Bef2 -> %After a ':' {Bef3,S2,_} = over_symbol(Bef2, , 0), - need_lparen(Bef3, fun () -> expand_function_name(S2, S1) end); + need_lparen(Bef3, fun () -> expand_function_name(S2, S1, " ") end); Bef2 -> - need_lparen(Bef2, fun () -> expand_module_name(S1) end) + need_lparen(Bef2, fun () -> expand_module_name(S1, ":") end) end. need_lparen(Bef, Do) -> @@ -61,26 +56,35 @@ %% expand_module_name(Word) %% end. -expand_module_name(Prefix) -> - match(Prefix, code:all_loaded(), ":"). +expand_module_name("", _) -> + {no, , }; +expand_module_name(Prefix, CompleteChar) -> + ModPaths = {list_to_atom(M),P} || {M,P,_} <- code:all_available() , + match(Prefix, ModPaths, CompleteChar). -expand_function_name(ModStr, FuncPrefix) -> +expand_function_name(ModStr, FuncPrefix, CompleteChar) -> case to_symbol(ModStr) of - {ok,Mod} -> - case erlang:module_loaded(Mod) of - true -> - L = Mod:module_info(), - case lists:keyfind(exports, 1, L) of - {_, Exports} -> - match(FuncPrefix, Exports, " "); - _ -> - {no,,} - end; - false -> - {no,,} + {ok, Mod} -> + Exports = + case erlang:module_loaded(Mod) of + true -> + Mod:module_info(exports); + false -> + case beam_lib:chunks(code:which(Mod), exports) of + {ok, {Mod, {exports,E}}} -> + E; + _ -> + {no, , } + end + end, + case Exports of + {no, , } -> + {no, , }; + Exports -> + match(FuncPrefix, Exports, CompleteChar) end; error -> - {no,,} + {no, , } end. %% If it's a quoted symbol, atom_to_list/1 will do the wrong thing.
View file
_service:tar_scm:lfe-1.3.tar.gz/src/lfe_env.erl -> _service:tar_scm:lfe-2.1.1.tar.gz/src/lfe_env.erl
Changed
@@ -1,4 +1,4 @@ -%% Copyright (c) 2008-2016 Robert Virding +%% Copyright (c) 2008-2020 Robert Virding %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -21,13 +21,18 @@ -export(new/0,add_env/2, get_vars/1,clr_vars/1,set_vars/2,fold_vars/3, get_funs/1,clr_funs/1,set_funs/2,fold_funs/3,fold_macros/3, - add_vbinding/3,add_vbindings/2,is_vbound/2,get_vbinding/2, - fetch_vbinding/2,del_vbinding/2, - add_fbinding/4,add_fbindings/2, + get_recs/1,clr_recs/1,set_recs/2,fold_recs/3). + +-export(add_vbinding/3,add_vbindings/2,is_vbound/2,get_vbinding/2, + fetch_vbinding/2,del_vbinding/2). + +-export(add_fbinding/4,add_fbindings/2, is_fbound/3,get_fbinding/3,add_ibinding/5, add_mbinding/3,add_mbindings/2, is_mbound/2,get_mbinding/2). +-export(add_record/3,get_record/2). + %% Define access macros depending on whether we have maps. -ifdef(HAS_MAPS). -define(NEW(), #{}). @@ -55,7 +60,7 @@ -endif. %% The environment structure. --record(env, {vars=null,funs=null}). +-record(env, {vars=null,funs=null,recs=null}). %% -compile(export_all). @@ -70,6 +75,10 @@ %% set_funs(Funs, Env) -> Env. %% fold_funs(Fun, Acc, Env) -> Acc. %% fold_macros(Fun, Acc, Env) -> Acc. +%% get_recs(Env) -> Recs. +%% clr_recs(Env) -> Env. +%% set_recs(Recs, Env) -> Env. +%% fold_recs(Fun, Acc, Env) -> Acc. %% add_vbinding(Name, Val, Env) -> Env. %% add_vbindings({Name,Val}, Env) -> Env. %% is_vbound(Symb, Env) -> bool(). @@ -99,17 +108,19 @@ %% orddict with the name as key and the value is either the macro %% definition or a dict of arity definition. -new() -> #env{vars=?NEW(),funs=?NEW()}. +new() -> #env{vars=?NEW(),funs=?NEW(),recs=?NEW()}. -ifdef(HAS_MAPS). -add_env(#env{vars=Vs1,funs=Fs1}, #env{vars=Vs2,funs=Fs2}) -> +add_env(#env{vars=Vs1,funs=Fs1,recs=Rs1}, #env{vars=Vs2,funs=Fs2,recs=Rs2}) -> #env{vars=maps:merge(Vs2, Vs1), %Always take left env - funs=maps:merge(Fs2, Fs1)}. + funs=maps:merge(Fs2, Fs1), + recs=maps:merge(Rs2, Rs1)}. -else. -add_env(#env{vars=Vs1,funs=Fs1}, #env{vars=Vs2,funs=Fs2}) -> +add_env(#env{vars=Vs1,funs=Fs1,recs=Rs1}, #env{vars=Vs2,funs=Fs2,recs=Rs2}) -> Merge = fun (_, V1, _) -> V1 end, %Always take left env #env{vars=orddict:merge(Merge, Vs1, Vs2), - funs=orddict:merge(Merge, Fs1, Fs2)}. + funs=orddict:merge(Merge, Fs1, Fs2), + recs=orddict:merge(Merge, Rs1, Rs2)}. -endif. %% Accessing the variable table. @@ -145,6 +156,14 @@ end, ?FOLD(Ofun, Acc, Env#env.funs). +%% Accessing the record table. + +get_recs(Env) -> Env#env.recs. +clr_recs(Env) -> Env#env{recs=?NEW()}. +set_recs(Recs, Env) -> Env#env{recs=Recs}. +fold_recs(Fun, Acc, Env) -> + ?FOLD(Fun, Acc, Env#env.recs). + %% Variables. add_vbinding(N, V, #env{vars=Vs}=Env) -> @@ -185,7 +204,7 @@ add_fbindings(Fbs, #env{funs=Fs0}=Env) -> Fs1 = lists:foldl(fun ({N,A,V}, Fs) -> add_fbinding_1(N, A, {A,V}, Fs) end, - Fs0, Fbs), + Fs0, Fbs), Env#env{funs=Fs1}. add_ibinding(M, R, A, L, #env{funs=Fs0}=Env) -> @@ -220,7 +239,7 @@ add_mbindings(Fbs, #env{funs=Fs0}=Env) -> Fs1 = lists:foldl(fun ({N,V}, Fs) -> ?PUT(N, {macro,V}, Fs) end, - Fs0, Fbs), + Fs0, Fbs), Env#env{funs=Fs1}. is_mbound(N, #env{funs=Fs}) -> @@ -234,3 +253,14 @@ {ok,{macro,V}} -> {yes,V}; _ -> no end. + +%% Records. + +add_record(R, Fs, #env{recs=Rs}=Env) -> + Env#env{recs=?PUT(R, Fs, Rs)}. + +get_record(R, #env{recs=Rs}) -> + case ?FIND(R, Rs) of + {ok,Fs} -> {yes,Fs}; + error -> no + end.
View file
_service:tar_scm:lfe-1.3.tar.gz/src/lfe_eval.erl -> _service:tar_scm:lfe-2.1.1.tar.gz/src/lfe_eval.erl
Changed
@@ -1,4 +1,4 @@ -%% Copyright (c) 2008-2017 Robert Virding +%% Copyright (c) 2008-2021 Robert Virding %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -37,57 +37,75 @@ add_fbinding/4,add_fbindings/2, add_ibinding/5). --import(lists, reverse/1,all/2,map/2,foldl/3,foldr/3). -import(orddict, find/2,fetch/2,store/3,is_key/2). -compile({no_auto_import,apply/3}). %For our apply/3 function -deprecated(eval/1,eval/2,eval_list/2). -%% We do a lot of quoting! --define(Q(E), quote,E). --define(BQ(E), backquote,E). --define(C(E), comma,E). --define(C_A(E), 'comma-at',E). +-include("lfe.hrl"). -%% Define IS_MAP/1 macro for is_map/1 bif. --ifdef(HAS_MAPS). --define(IS_MAP(T), is_map(T)). --else. --define(IS_MAP(T), false). --endif. +-define(STACKTRACE, + element(2, erlang:process_info(self(), current_stacktrace))). + +-define(EVAL_ERROR(Error), erlang:raise(error, Error, ?STACKTRACE)). %% -compile(export_all). -%% Errors. +%% Errors which we generate. +%% Some of thse may also be generated by compiled code in which case +%% they will probably be caught in lfe_lib. + format_error(badarg) -> <<"bad argument">>; format_error({badmatch,Val}) -> - lfe_io:format1(<<"bad match: ~w">>, Val); -format_error({unbound_symb,S}) -> + lfe_io:format1(<<"no match of value ~w">>, Val); +format_error({unbound_symbol,S}) -> lfe_io:format1(<<"symbol ~w is unbound">>, S); -format_error({undefined_func,{F,A}}) -> - lfe_io:format1(<<"undefined function ~w/~w">>, F,A); +format_error({undefined_function,{F,A}}) -> + lfe_io:format1(<<"function ~w/~w undefined">>, F,A); format_error(if_expression) -> <<"non-boolean if test">>; format_error(function_clause) -> <<"no function clause matching">>; format_error({case_clause,Val}) -> - lfe_io:format1(<<"no case clause matching ~.P">>, Val,10); -format_error(illegal_guard) -> <<"illegal guard">>; -format_error(illegal_bitsize) -> <<"illegal bitsize">>; -format_error(illegal_bitseg) -> <<"illegal bitsegment">>; + format_value(Val, <<"no case clause matching ">>); +format_error(illegal_guard) -> <<"illegal guard expression">>; +format_error(illegal_bitsize) -> <<"illegal bit size">>; +format_error(illegal_bitseg) -> <<"illegal bit segment">>; format_error({illegal_pattern,Pat}) -> - lfe_io:format1(<<"illegal pattern ~w">>, Pat); + format_value(Pat, <<"illegal pattern ">>); format_error({illegal_literal,Lit}) -> - lfe_io:format1(<<"illegal literal value ~w">>, Lit); + format_value(Lit, <<"illegal literal value ">>); format_error({illegal_mapkey,Key}) -> lfe_io:format1(<<"illegal map key ~w">>, Key); -format_error(bad_arity) -> <<"arity mismatch">>; +format_error(bad_head_arity) -> <<"function head arity mismatch">>; format_error({argument_limit,Arity}) -> lfe_io:format1(<<"too many arguments ~w">>, Arity); format_error({bad_form,Form}) -> lfe_io:format1(<<"bad ~w form">>, Form); +%% Try-catches. +format_error({try_clause,V}) -> + format_value(V, <<"no try clause matching ">>); +format_error({illegal_exception,E}) -> + lfe_io:format1(<<"illegal exception ~w">>, E); +%% Records. +format_error({undefined_record,Name}) -> + lfe_io:format1(<<"record ~w undefined">>, Name); +format_error({undefined_record_field,Name,Field}) -> + lfe_io:format1(<<"field ~w undefined in record ~w">>, Field,Name); +format_error({missing_record_field_value,Field}) -> + lfe_io:format1(<<"missing value to field ~w in record">>, Field); +%% Structs. +format_error({undefined_struct,Name}) -> + lfe_io:format1(<<"struct ~w undefined">>, Name); +format_error({undefined_struct_field,Name,Field}) -> + lfe_io:format1(<<"field ~w undefined in struct ~w">>, Field,Name); +format_error({missing_struct_field_value,Field}) -> + lfe_io:format1(<<"missing value to field ~w in struct">>, Field); %% Everything we don't recognise or know about. format_error(Error) -> lfe_io:prettyprint1(Error). +format_value(Val, ErrStr) -> + lfe_io:format1(<<"~s~.P">>, ErrStr,Val,10). + %% eval(Sexpr) -> Value. %% eval(Sexpr, Env) -> Value. @@ -162,31 +180,98 @@ setelement(eval_expr(I, Env), eval_expr(Tup, Env), eval_expr(V, Env)); eval_expr(binary|Bs, Env) -> eval_binary(Bs, Env); eval_expr(map|As, Env) -> - Pairs = map_pairs(As, Env), - maps:from_list(Pairs); -eval_expr('mref',Map,K, Env) -> - Key = map_key(K, Env), - maps:get(Key, eval_expr(Map, Env)); -eval_expr('mset',M|As, Env) -> - Map = eval_expr(M, Env), - Pairs = map_pairs(As, Env), - foldl(fun maps_put/2, Map, Pairs); -eval_expr('mupd',M|As, Env) -> - Map = eval_expr(M, Env), - Pairs = map_pairs(As, Env), - foldl(fun maps_update/2, Map, Pairs); -eval_expr('map-get',Map,K, Env) -> - eval_expr(mref,Map,K, Env); -eval_expr('map-set',M|As, Env) -> - eval_expr(mset,M|As, Env); -eval_expr('map-update',M|As, Env) -> - eval_expr(mupd,M|As, Env); -eval_expr(function,Fun,Ar, Env) -> - %% Build a lambda which can be applied. - Vs = new_vars(Ar), - eval_lambda(lambda,Vs,Fun|Vs, Env); -eval_expr(function,M,F,Ar, _) -> - erlang:make_fun(M, F, Ar); + eval_map(As, Env); +eval_expr('msiz',Map, Env) -> + eval_map_size(msiz, Map, Env); +eval_expr('mref',Map,Key, Env) -> + eval_map_get(mref, Map, Key, Env); +eval_expr('mset',Map|As, Env) -> + eval_map_set(mset, Map, As, Env); +eval_expr('mupd',Map|As, Env) -> + eval_map_update(mupd, Map, As, Env); +eval_expr('mrem',Map|Ks, Env) -> + eval_map_remove(mrem, Map, Ks, Env); +eval_expr('map-size',Map, Env) -> + eval_map_size('map-size', Map, Env); +eval_expr('map-get',Map,Key, Env) -> + eval_map_get('map-get', Map, Key, Env); +eval_expr('map-set',Map|As, Env) -> + eval_map_set('map-set', Map, As, Env); +eval_expr('map-update',Map|As, Env) -> + eval_map_update('map-update', Map, As, Env); +eval_expr('map-remove',Map|Ks, Env) -> + eval_map_remove('map-remove', Map, Ks, Env); +%% Record special forms. +eval_expr('record',Name|Fs, Env) -> + make_record_tuple(Name, Fs, Env); +%% make-record has been deprecated but we sill accept it for now. +eval_expr('make-record',Name|As, Env) -> + eval_expr('record',Name|As, Env); +eval_expr('is-record',E,Name, Env) -> + Ev = eval_expr(E, Env), + case lfe_env:get_record(Name, Env) of + {yes,Fields} -> + is_valid_record(Ev, Name, Fields); + no -> undefined_record_error(Name) + end; +eval_expr('record-index',Name,F, Env) -> + case lfe_env:get_record(Name, Env) of + {yes,Fields} -> + get_field_index(Name, Fields, F); + no -> undefined_record_error(Name) + end; +eval_expr('record-field',E,Name,F, Env) -> + Ev = eval_expr(E, Env), + case lfe_env:get_record(Name, Env) of + {yes,Fields} -> + case is_valid_record(Ev, Name, Fields) of + true -> + Index = get_field_index(Name, Fields, F), + element(Index, Ev); + false -> + eval_error({badrecord,Name,Ev}) + end; + no -> undefined_record_error(Name) + end; +eval_expr('record-update',E,Name|Args, Env) -> + Ev = eval_expr(E, Env), + update_record_tuple(Ev, Name, Args, Env); +%% Struct special forms. +eval_expr('struct',Name|Fs, Env) -> + make_struct_map(Name, Fs, Env); +eval_expr('is-struct',E, Env) -> + Ev = eval_expr(E, Env), + test_is_struct(Ev); +eval_expr('is-struct',E,Name, Env) -> + Ev = eval_expr(E, Env), + test_is_struct(Ev, Name);
View file
_service:tar_scm:lfe-2.1.1.tar.gz/src/lfe_eval_bits.erl
Added
@@ -0,0 +1,299 @@ +%% Copyright (c) 2021 Robert Virding +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. + +%% File : lfe_eval_bits.erl +%% Author : Robert Virding +%% Purpose : Lisp Flavoured Erlang interpreter functions for binaries. + +%%% We follow Erlang here in many cases even though it is sometimes a +%%% bit strange. In a fun argument where when matching a binary we +%%% import the size of bitseg as a variable from the environment not +%%% just from earlier segments. No other argument variables are +%%% imported. + +-module(lfe_eval_bits). + +-export(expr_bitsegs/2,match_bitsegs/4). + +-import(lists, foldl/3,foldr/3). + +-import(lfe_env, add_vbinding/3,add_vbindings/2,get_vbinding/2, + add_fbinding/4,add_fbindings/2, + add_ibinding/5). +-import(orddict, find/2,fetch/2,store/3,is_key/2). + +-include("lfe.hrl"). + +-define(STACKTRACE, + element(2, erlang:process_info(self(), current_stacktrace))). + +-define(EVAL_ERROR(Error), erlang:raise(error, Error, ?STACKTRACE)). + +%% expr_bitsegs(Bitsegs, EvalFun) -> Binary. +%% Construct a binary from Bitsegs. This code is taken from +%% eval_bits.erl. Pass in an evaluator function to be used when +%% evaluating vale and size expression. + +expr_bitsegs(Segs, Eval) -> + Vsps = get_bitsegs(Segs), + eval_bitsegs(Vsps, Eval). + +get_bitsegs(Segs) -> + foldr(fun (S, Vs) -> get_bitseg(S, Vs) end, , Segs). + +%% get_bitseg(Bitseg, ValSpecs) -> ValSpecs. +%% A bitseg is either an atomic value, a list of value and specs, or +%% a string. + +get_bitseg(Val|Specs=Seg, Vsps) -> + case lfe_lib:is_posint_list(Seg) of %Is bitseg a string? + true -> %A string + {Sz,Ty} = get_bitspecs(), + foldr(fun (V, Vs) -> {V,Sz,Ty}|Vs end, Vsps, Seg); + false -> %A value and spec + {Sz,Ty} = get_bitspecs(Specs), + case lfe_lib:is_posint_list(Val) of %Is Val a string? + true -> foldr(fun (V, Vs) -> {V,Sz,Ty}|Vs end, Vsps, Val); + false -> {Val,Sz,Ty}|Vsps %The default + end + end; +get_bitseg(Val, Vsps) -> + {Sz,Ty} = get_bitspecs(), + {Val,Sz,Ty}|Vsps. + +%% get_bitspec(Specs) -> {Size,Type}. +%% Get the error handling as we want it. + +get_bitspecs(Ss) -> + case lfe_bits:get_bitspecs(Ss) of + {ok,Sz,Ty} -> {Sz,Ty}; + {error,Error} -> eval_error(Error) + end. + +%% eval_bitsegs(VSTys, EvalFun) -> Binary. +%% The evaluator function is use to evaluate the value and size +%% fields. + +eval_bitsegs(Vsps, Eval) -> + foldl(fun ({Val,Sz,Ty}, Acc) -> + Bin = eval_bitseg(Val, Sz, Ty, Eval), + <<Acc/bitstring,Bin/bitstring>> + end, <<>>, Vsps). + +eval_bitseg(Val, Sz, Ty, Eval) -> + V = Eval(Val), + eval_exp_bitseg(V, Sz, Eval, Ty). + +%% eval_exp_bitseg(Value, Size, EvalSize, {Type,Unit,Sign,Endian}) -> Binary. + +eval_exp_bitseg(Val, Size, Eval, Type) -> + case Type of + %% Integer types. + {integer,Un,Si,En} -> + Sz = Eval(Size), + eval_int_bitseg(Val, Sz*Un, Si, En); + %% Unicode types, ignore unused fields. + {utf8,_,_,_} -> <<Val/utf8>>; + {utf16,_,_,En} -> eval_utf16_bitseg(Val, En); + {utf32,_,_,En} -> eval_utf32_bitseg(Val, En); + %% Float types. + {float,Un,_,En} -> + Sz = Eval(Size), + eval_float_bitseg(Val, Sz*Un, En); + %% Binary types. + {binary,Unit,_,_} -> + if Size == all -> + case bit_size(Val) of + Sz when Sz rem Unit =:= 0 -> + <<Val:Sz/bitstring>>; + _ -> badarg_error() + end; + true -> + Sz = Eval(Size), + <<Val:(Sz*Unit)/bitstring>> + end + end. + +eval_int_bitseg(Val, Sz, signed, big) -> <<Val:Sz/signed>>; +eval_int_bitseg(Val, Sz, unsigned, big) -> <<Val:Sz>>; +eval_int_bitseg(Val, Sz, signed, little) -> <<Val:Sz/little-signed>>; +eval_int_bitseg(Val, Sz, unsigned, little) -> <<Val:Sz/little>>; +eval_int_bitseg(Val, Sz, signed, native) -> <<Val:Sz/native-signed>>; +eval_int_bitseg(Val, Sz, unsigned, native) -> <<Val:Sz/native>>. + +eval_utf16_bitseg(Val, big) -> <<Val/utf16-big>>; +eval_utf16_bitseg(Val, little) -> <<Val/utf16-little>>; +eval_utf16_bitseg(Val, native) -> <<Val/utf16-native>>. + +eval_utf32_bitseg(Val, big) -> <<Val/utf32-big>>; +eval_utf32_bitseg(Val, little) -> <<Val/utf32-little>>; +eval_utf32_bitseg(Val, native) -> <<Val/utf32-native>>. + +eval_float_bitseg(Val, Sz, big) -> <<Val:Sz/float>>; +eval_float_bitseg(Val, Sz, little) -> <<Val:Sz/float-little>>; +eval_float_bitseg(Val, Sz, native) -> <<Val:Sz/float-native>>. + +%% match_bitsegs(BitSegs, Binary PatBindings, Env) -> {yes,PatBindings} | no. +%% Match Bitsegs against Binary. This code is taken from +%% eval_bits.erl. Bitspec errors generate an error. Bad matches +%% result in an error, we use catch to trap it. + +match_bitsegs(Segs, Bin, Pbs0, Env) -> + Psps = get_bitsegs(Segs), + match_bitsegs(Psps, Bin, , Pbs0, Env). + +match_bitsegs({Pat,Sz,Ty}|Psps, Bin0, Bbs0, Pbs0, Env) -> + case match_bitseg(Pat, Sz, Ty, Bin0, Bbs0, Pbs0, Env) of + {yes,Bin1,Bbs1,Pbs1} -> + match_bitsegs(Psps, Bin1, Bbs1, Pbs1, Env); + no -> no + end; +match_bitsegs(, <<>>, _, Pbs, _) -> {yes,Pbs}; %Reached the end of both +match_bitsegs(, _, _, _, _) -> no. %More to go + +match_bitseg(Pat, Size, Type, Bin0, Bbs0, Pbs0, Env) -> + Sz = get_pat_bitsize(Size, Type, Bbs0, Pbs0, Env), + case catch {ok,get_pat_bitseg(Bin0, Sz, Type)} of + {ok,{Val,Bin1}} -> + case match_bitexpr(Pat, Val, Bbs0, Pbs0, Env) of + {yes,Bbs1,Pbs1} -> {yes,Bin1,Bbs1,Pbs1}; + no -> no + end; + _ -> no + end. + +get_pat_bitsize(all, {Ty,_,_,_}, _, _, _) -> + if Ty =:= binary -> all; + true -> eval_error(illegal_bitsize) + end; +get_pat_bitsize(undefined, {Ty,_,_,_}, _, _, _) -> + if Ty =:= utf8; Ty =:= utf16; Ty =:= utf32 -> undefined; + true -> eval_error(illegal_bitsize) + end; +get_pat_bitsize(S, _, _, _, _) when is_integer(S) -> S; +get_pat_bitsize(S, _, Bbs, _, Env) when is_atom(S) -> + %% Variable either in environment or bound in binary. + case get_vbinding(S, Env) of + {yes,V} -> V; + no -> + case find(S, Bbs) of + {ok,V} -> V; + error -> unbound_symb_error(S) + end + end. + +match_bitexpr(N, Val, Bbs, Pbs, _) when is_number(N) -> + if N =:= Val -> {yes,Bbs,Pbs}; + true -> no + end;
View file
_service:tar_scm:lfe-1.3.tar.gz/src/lfe_gen.erl -> _service:tar_scm:lfe-2.1.1.tar.gz/src/lfe_gen.erl
Changed
@@ -1,4 +1,4 @@ -%% Copyright (c) 2008-2016 Robert Virding +%% Copyright (c) 2008-2020 Robert Virding %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License.
View file
_service:tar_scm:lfe-1.3.tar.gz/src/lfe_init.erl -> _service:tar_scm:lfe-2.1.1.tar.gz/src/lfe_init.erl
Changed
@@ -1,4 +1,4 @@ -%% Copyright (c) 2008-2014 Robert Virding +%% Copyright (c) 2008-2020 Robert Virding %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -29,49 +29,62 @@ -export(start/0). +-include("lfe.hrl"). + -define(OK_STATUS, 0). -define(ERROR_STATUS, 127). %% Start LFE running a script or the shell depending on arguments. start() -> - case init:get_plain_arguments() of - "-lfe_eval"|As -> %Run a command string - user:start(), %Start user for io - run_string(As); - S|As -> %Run a script - user:start(), %Start user for io - run_file(S|As); - -> %Run a shell - user_drv:start('tty_sl -c -e',{lfe_shell,start,}) + case collect_args(init:get_plain_arguments()) of + {,} -> %Run a shell + user_drv:start('tty_sl -c -e',{lfe_shell,start,}); + {Es,Script} -> + user:start(), + %% io:format("es: ~p\n", {Es,Script}), + run_evals_script(Es, Script) end. -run_file(S|As) -> - Script = fun () -> lfe_shell:run_script(S, As) end, - spawn_link(fun () -> run_script(Script) end). +collect_args(E,S|As) when E == "-lfe_eval" ; E == "-eval" ; E == "-e" -> + {Es,Script} = collect_args(As), + {S ++ Es,Script}; +collect_args(E) when E == "-lfe_eval" ; E == "-eval" ; E == "-e" -> + {,}; +collect_args(As) -> {,As}. %Remaining become script + +%% run_evals_script(Evals, Script) -> Pid. +%% Firat evaluate all the eval strings if any then the script if +%% there is one. The state from the string is past into the +%% script. We can handle no strings and no script. -run_string() -> run_string(, ); %No command -run_string("--") -> run_string(, ); %No command -run_string(S,"--"|As) -> run_string(S, As); -run_string(S|As) -> run_string(S, As). +run_evals_script(Evals, Script) -> + S = fun () -> + St = lfe_shell:run_strings(Evals), + case Script of + F|As -> + lfe_shell:run_script(F, As, St); + -> {,St} + end + end, + spawn_link(fun () -> run_script(S) end). -run_string(, _) -> %No command - io:put_chars(user, "eval: missing command\n"), - halt(?ERROR_STATUS); -run_string(S, As) -> - Script = fun () -> lfe_shell:run_string(S, As) end, - spawn_link(fun () -> run_script(Script) end). +%% run_script(Script) +%% Run a script and terminate the erlang process afterwards. run_script(Script) -> try - Script(), + Script(), %Evaluate the script + %% For some reason we need to wait a bit before stopping. + timer:sleep(1), init:stop(?OK_STATUS) catch - Class:Error -> - St = erlang:get_stacktrace(), %Need to get this first - Sf = fun (_) -> false end, + ?CATCH(Class, Error, Stack) + Sf = fun ({M,_F,_A,_L}) -> + M /= lfe_eval + end, Ff = fun (T, I) -> lfe_io:prettyprint1(T, 15, I, 80) end, - Cs = lfe_lib:format_exception(Class, Error, St, Sf, Ff, 1), + Cs = lfe_lib:format_exception(Class, Error, Stack, Sf, Ff, 1), io:put_chars(Cs), halt(?ERROR_STATUS) end.
View file
_service:tar_scm:lfe-1.3.tar.gz/src/lfe_internal.erl -> _service:tar_scm:lfe-2.1.1.tar.gz/src/lfe_internal.erl
Changed
@@ -1,4 +1,4 @@ -%% Copyright (c) 2016 Robert Virding +%% Copyright (c) 2016-2021 Robert Virding %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -14,13 +14,16 @@ %% File : lfe_internal.erl %% Author : Robert Virding -%% Purpose : Define Lisp Flavoured Erlang internal bifs, guards. +%% Purpose : Define Lisp Flavoured Erlang internals. + +%%% Define LFE internal bifs, guards and other internal stuff. -module(lfe_internal). %% General library functions. -export(is_bif/2,is_guard_bif/2,is_erl_bif/2,is_lfe_bif/2). -export(is_core_form/1,is_core_func/2). +-export(is_type/2). %% -compile(export_all). @@ -62,12 +65,30 @@ is_core_form(tset) -> true; is_core_form(binary) -> true; is_core_form(map) -> true; +is_core_form(msiz) -> true; is_core_form(mref) -> true; is_core_form(mset) -> true; is_core_form(mupd) -> true; +is_core_form(mrem) -> true; +is_core_form('map-size') -> true; is_core_form('map-get') -> true; is_core_form('map-set') -> true; is_core_form('map-update') -> true; +is_core_form('map-remove') -> true; +%% Core record special forms. +is_core_form('record') -> true; +%% make-record has been deprecated but we sill accept it for now. +is_core_form('make-record') -> true; +is_core_form('is-record') -> true; +is_core_form('record-index') -> true; +is_core_form('record-field') -> true; +is_core_form('record-update') -> true; +%% Core struct special forms. +is_core_form('struct') -> true; +is_core_form('is-struct') -> true; +is_core_form('struct-field') -> true; +is_core_form('struct-update') -> true; +%% Function forms. is_core_form(function) -> true; %% Core closure special forms. is_core_form(lambda) -> true; @@ -85,6 +106,11 @@ is_core_form('try') -> true; is_core_form('funcall') -> true; is_core_form(call) -> true; +%% List/binary comprehensions. +is_core_form('lc') -> true; +is_core_form('list-comp') -> true; +is_core_form('bc') -> true; +is_core_form('binary-comp') -> true; %% Core definition special forms. is_core_form('eval-when-compile') -> true; is_core_form('define-module') -> true; @@ -94,6 +120,8 @@ is_core_form('define-function-spec') -> true; is_core_form('define-function') -> true; is_core_form('define-macro') -> true; +is_core_form('define-record') -> true; +is_core_form('define-struct') -> true; %% And don't forget when. is_core_form('when') -> true; %% Everything else is not a core form. @@ -113,12 +141,35 @@ is_core_func(tset, 3) -> true; is_core_func(binary, Ar) when Ar >= 0 -> true; is_core_func(map, Ar) when Ar >= 0, (Ar rem 2) =:= 0 -> true; +is_core_func(msiz, 1) -> true; is_core_func(mref, 2) -> true; -is_core_func(mset, Ar) when Ar >= 0, (Ar rem 2) =:= 1 -> true; -is_core_func(mupd, Ar) when Ar >= 0, (Ar rem 2) =:= 1 -> true; +is_core_func(mset, Ar) when Ar >= 1, (Ar rem 2) =:= 1 -> true; +is_core_func(mupd, Ar) when Ar >= 1, (Ar rem 2) =:= 1 -> true; +is_core_func(mrem, Ar) when Ar >= 1 -> true; +is_core_func('map-size', 1) -> true; is_core_func('map-get', 2) -> true; -is_core_func('map-set', Ar) when Ar >= 0, (Ar rem 2) =:= 1 -> true; -is_core_func('map-upd', Ar) when Ar >= 0, (Ar rem 2) =:= 1 -> true; +is_core_func('map-set', Ar) when Ar >= 1, (Ar rem 2) =:= 1 -> true; +is_core_func('map-update', Ar) when Ar >= 1, (Ar rem 2) =:= 1 -> true; +is_core_func('map-remove', Ar) when Ar >= 1 -> true; +%% Core record special functions. +is_core_func('record', Ar) when Ar >= 1, (Ar rem 2) =:= 1 -> true; +%% make-record has been deprecated but we sill accept it for now. +is_core_func('make-record', Ar) when Ar >= 1, (Ar rem 2) =:= 1 -> true; +is_core_func('is-record', 2) -> true; +is_core_func('record-index', 2) -> true; +is_core_func('record-field', 3) -> true; +is_core_func('record-update', Ar) when Ar >= 2, (Ar rem 2) =:= 0 -> true; +%% Core struct special functions. +is_core_func('struct', Ar) when Ar >= 1, (Ar rem 2) =:= 1 -> true; +is_core_func('is-struct', Ar) when Ar =:= 1; Ar =:= 2 -> true; +is_core_func('struct-field', 3) -> true; +is_core_func('struct-update', Ar) when Ar >= 2, (Ar rem 2) =:= 0 -> true; +%% List/binary comprehensions. +is_core_func('lc', 2) -> true; +is_core_func('list-comp', 2) -> true; +is_core_func('bc', 2) -> true; +is_core_func('binary-comp', 2) -> true; +%% Core control special functions. is_core_func(funcall, Ar) when Ar >= 1 -> true; is_core_func(call, Ar) when Ar >= 2 -> true; is_core_func(_, _) -> false. @@ -138,3 +189,16 @@ is_lfe_bif('macroexpand-all', 1) -> true; is_lfe_bif('macroexpand-all', 2) -> true; is_lfe_bif(_, _) -> false. + +%% is_type(NAme, Arity) -> bool(). +%% Return true if Name/Arity is a predefined type. + +is_type('UNION', Ar) -> is_integer(Ar) and (Ar >= 0); +is_type(call, Ar) -> is_integer(Ar) and (Ar >= 0); +is_type(lambda, Ar) -> is_integer(Ar) and (Ar >= 0); +is_type(map, Ar) -> is_integer(Ar) and (Ar >= 0); +is_type(range, 2) -> true; +is_type(bitstring, 2) -> true; +is_type(tuple, Ar) -> is_integer(Ar) and (Ar >= 0); +is_type(Name, Arity) -> + erl_internal:is_type(Name, Arity).
View file
_service:tar_scm:lfe-1.3.tar.gz/src/lfe_io.erl -> _service:tar_scm:lfe-2.1.1.tar.gz/src/lfe_io.erl
Changed
@@ -1,4 +1,4 @@ -%% Copyright (c) 2008-2016 Robert Virding +%% Copyright (c) 2008-2020 Robert Virding %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -24,7 +24,7 @@ -module(lfe_io). --export(parse_file/1,read_file/1). +-export(parse_file/1,parse_file/2,read_file/1,read_file/2). -export(read/0,read/1,read/2,read_line/0,read_line/1,read_line/2). -export(read_string/1). -export(scan_sexpr/2,scan_sexpr/3). @@ -38,68 +38,79 @@ -import(lists, flatten/1,reverse/1,reverse/2,map/2,mapfoldl/3,all/2). -%% Define IS_MAP/1 macro for is_map/1 bif. --ifdef(HAS_MAPS). --define(IS_MAP(T), is_map(T)). --else. --define(IS_MAP(T), false). --endif. +-include("lfe.hrl"). -%% parse_file(FileName) -> {ok,{Sexpr,Line}} | {error,Error}. +%% parse_file(FileName|Fd, Line) -> {ok,{Sexpr,Line}} | {error,Error}. %% Parse a file returning the raw sexprs (as it should be) and line %% numbers of start of each sexpr. Handle errors consistently. -parse_file(Name) -> - with_token_file(Name, fun (Ts) -> parse_file1(Ts, , ) end). +parse_file(Name) -> parse_file(Name, 1). -parse_file1(_|_=Ts0, Pc0, Ss) -> +parse_file(Name, Line) -> + with_token_file(Name, + fun (Ts, Lline) -> parse_file1(Ts, Lline, , ) end, + Line). + +parse_file1(_|_=Ts0, Lline, Pc0, Ss) -> case lfe_parse:sexpr(Pc0, Ts0) of - {ok,L,S,Ts1} -> parse_file1(Ts1, , {S,L}|Ss); + {ok,L,S,Ts1} -> parse_file1(Ts1, Lline, , {S,L}|Ss); {more,Pc1} -> %% Need more tokens but there are none, so call again to %% generate an error message. - {error,E,_} = lfe_parse:sexpr(Pc1, {eof,99999}), + {error,E,_} = lfe_parse:sexpr(Pc1, {eof,Lline}), {error,E}; {error,E,_} -> {error,E} end; -parse_file1(, _, Ss) -> {ok,reverse(Ss)}. +parse_file1(, _, _, Ss) -> {ok,reverse(Ss)}. -%% read_file(FileName) -> {ok,Sexpr} | {error,Error}. +%% read_file(FileName|Fd, Line) -> {ok,Sexpr} | {error,Error}. %% Read a file returning the raw sexprs (as it should be). -read_file(Name) -> - with_token_file(Name, fun (Ts) -> read_file1(Ts, ) end). +read_file(Name) -> read_file(Name, 1). + +read_file(Name, Line) -> + with_token_file(Name, + fun (Ts, Lline) -> read_file1(Ts, Lline, ) end, + Line). -read_file1(_|_=Ts0, Ss) -> +read_file1(_|_=Ts0, Lline, Ss) -> case lfe_parse:sexpr(Ts0) of - {ok,_,S,Ts1} -> read_file1(Ts1, S|Ss); + {ok,_,S,Ts1} -> read_file1(Ts1, Lline, S|Ss); {more,Pc1} -> %% Need more tokens but there are none, so call again to %% generate an error message. - {error,E,_} = lfe_parse:sexpr(Pc1, {eof,99999}), + {error,E,_} = lfe_parse:sexpr(Pc1, {eof,Lline}), {error,E}; {error,E,_} -> {error,E} end; -read_file1(, Ss) -> {ok,reverse(Ss)}. +read_file1(, _, Ss) -> {ok,reverse(Ss)}. -%% with_token_file(FileName, DoFunc) -%% Open the file, scan all LFE tokens and apply DoFunc on them. +%% with_token_file(FileName|Fd, DoFunc, Line) +%% Open the file, scan all LFE tokens and apply DoFunc on them. If +%% file:open fails with badarg then try assuming it is a fd. Note +%% that a new file starts at line 1. -with_token_file(Name, Do) -> +with_token_file(Name, Do, Line) -> case file:open(Name, read) of - {ok,F} -> - Ret = case io:request(F, {get_until,unicode,'',lfe_scan,tokens,1}) of - {ok,Ts,_} -> Do(Ts); - {error,Error,_} -> {error,Error} - end, - file:close(F), %Close the file - Ret; % and return value + {ok,Fd} -> + with_token_file_fd(Fd, Do, 1); %Start at line 1 + {error,badarg} -> + %% Could be a fd so use it as it is one. + with_token_file_fd(Name, Do, Line); {error,Error} -> {error,{none,file,Error}} end. -%% read() -> {ok,Sexpr} | {error,Error}. -%% read(Prompt) -> {ok,Sexpr} | {error,Error}. -%% read(IoDevice, Prompt) -> {ok,Sexpr} | {error,Error}. +with_token_file_fd(Fd, Do, Line) -> %Called with a file descriptor + Ret = case io:request(Fd, {get_until,unicode,'',lfe_scan,tokens,Line}) of + {ok,Ts,Lline} -> Do(Ts, Lline); + {error,Error,_} -> {error,Error} + end, + file:close(Fd), %Close the file + Ret. % and return value + +%% read() -> {ok,Sexpr} | {error,Error} | eof. +%% read(Prompt) -> {ok,Sexpr} | {error,Error} | eof. +%% read(IoDevice, Prompt) -> {ok,Sexpr} | {error,Error} | eof. %% A simple read function. It is not line oriented and stops as soon %% as it has consumed enough. @@ -113,9 +124,9 @@ {eof,_} -> eof end. -%% read_line() -> {ok,Sexpr} | {error,Error}. -%% read_line(Prompt) -> {ok,Sexpr} | {error,Error}. -%% read_line(IoDevice, Prompt) -> {ok,Sexpr} | {error,Error}. +%% read_line() -> {ok,Sexpr} | {error,Error} | eof. +%% read_line(Prompt) -> {ok,Sexpr} | {error,Error} | eof. +%% read_line(IoDevice, Prompt) -> {ok,Sexpr} | {error,Error} | eof. %% A simple read function. It is line oriented and reads whole lines %% until it has consumed enough characters. Left-over characters in %% the last line are discarded. @@ -133,6 +144,7 @@ case scan_sexpr(C0, Cs0, L0) of {done,{ok,Ret,_L1},_Cs1} -> {ok,Ret}; {done,{error,Error,_},_Cs1} -> {error,Error}; + {done,{eof,_},_} -> eof; {more,C1} -> read_line_1(Io, P, C1, L0) end
View file
_service:tar_scm:lfe-1.3.tar.gz/src/lfe_io_format.erl -> _service:tar_scm:lfe-2.1.1.tar.gz/src/lfe_io_format.erl
Changed
@@ -1,4 +1,4 @@ -%% Copyright (c) 2008-2016 Robert Virding +%% Copyright (c) 2008-2020 Robert Virding %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -26,91 +26,104 @@ -import(lists, reverse/1,foldl/3). +-record(cstruct, {cchar, %Control character + args, %Control arguments + width, %Field width + adjust, %Adjust left/right + prec, %Precision + pad %Pad character + }). + %% -compile(export_all). fwrite1(Format, Data) -> - Cs = scan(Format, Data), - Pc = pcount(Cs), - build(Cs, Pc, 0). - -%% scan(Format, Args) -> FormatList. - -scan(Format, Args) when is_binary(Format) -> - scan(binary_to_list(Format), Args); -scan(Format, Args) -> - collect(Format, Args). - -%% collect(Format, Args) -> FormatList. - -collect($~|Fmt0, As0) -> - {C,Fmt1,As1} = collect_cseq(Fmt0, As0), - C|collect(Fmt1, As1); -collect(C|Fmt, Args) -> - C|collect(Fmt, Args); + Cstructs = scan(Format, Data), + Pc = pcount(Cstructs), + build(Cstructs, Pc, 0). + +%% scan(Format, Data) -> OutputChars. + +scan(Format, Data) when is_binary(Format) -> + scan(binary_to_list(Format), Data); +scan(Format, Data) -> + collect(Format, Data). + +%% collect(Format, Data) -> ControlStruct. +%% Collect all the control structures and characters built from the +%% format and the data. + +collect($~|Fmt0, Data0) -> + {Cstruct,Fmt1,Data1} = collect_cseq(Fmt0, Data0), + Cstruct|collect(Fmt1, Data1); +collect(C|Fmt, Data) -> + %% Just return the character in format. + C|collect(Fmt, Data); collect(, ) -> . -%% collect_cseq(Format, Args) -> -%% {{Control,ControlArgs,Field,Adjust,Precision,Pad},Format,Args}. +%% collect_cseq(Format, Data) -> +%% {ControlStruct,Format,Data}. -collect_cseq(Fmt0, As0) -> - {F,Ad,Fmt1,As1} = field_width(Fmt0, As0), - {P,Fmt2,As2} = precision(Fmt1, As1), - {Pad,Fmt3,As3} = pad_char(Fmt2, As2), - {C,As,Fmt4,As4} = collect_cc(Fmt3, As3), - {{C,As,F,Ad,P,Pad},Fmt4,As4}. +collect_cseq(Fmt0, Data0) -> + {Width,Ad,Fmt1,Data1} = field_width(Fmt0, Data0), + {P,Fmt2,Data2} = precision(Fmt1, Data1), + {Pad,Fmt3,Data3} = pad_char(Fmt2, Data2), + {C,Args,Fmt4,Data4} = collect_cc(Fmt3, Data3), + {#cstruct{cchar=C,args=Args,width=Width,adjust=Ad,prec=P,pad=Pad}, + Fmt4,Data4}. -%% field_width(Format, Args) -> {Field,Adjust,Format,Args}. -%% precision(Format, Args) -> {Precision,Format,Args}. -%% pad_char(Format, Args) -> {Field,Adjust,Format,Args}. +%% field_width(Format, Data) -> {Field,Adjust,Format,Data}. +%% precision(Format, Data) -> {Precision,Format,Data}. +%% pad_char(Format, Data) -> {Field,Adjust,Format,Data}. %% Extract the field width/precision/pad char from the format -field_width($-|Fmt0, Args0) -> - {F,Fmt,Args} = field_value(Fmt0, Args0), - field_width(-F, Fmt, Args); -field_width(Fmt0, Args0) -> - {F,Fmt,Args} = field_value(Fmt0, Args0), - field_width(F, Fmt, Args). - -field_width(F, Fmt, Args) when F < 0 -> - {-F,left,Fmt,Args}; -field_width(F, Fmt, Args) when F >= 0 -> - {F,right,Fmt,Args}. - -precision($.|Fmt, Args) -> field_value(Fmt, Args); -precision(Fmt, Args) -> {none,Fmt,Args}. - -field_value($*|Fmt, A|Args) when is_integer(A) -> - {A,Fmt,Args}; -field_value(C|Fmt, Args) when is_integer(C), C >= $0, C =< $9 -> - field_value(C|Fmt, Args, 0); -field_value(Fmt, Args) -> - {none,Fmt,Args}. - -field_value(C|Fmt, Args, F) when is_integer(C), C >= $0, C =< $9 -> - field_value(Fmt, Args, 10*F + (C - $0)); -field_value(Fmt, Args, F) -> %Default case - {F,Fmt,Args}. - -pad_char($.,$*|Fmt, Pad|Args) -> {Pad,Fmt,Args}; -pad_char($.,Pad|Fmt, Args) -> {Pad,Fmt,Args}; -pad_char(Fmt, Args) -> {$\s,Fmt,Args}. - -%% pcount(ControlC) -> Count. +field_width($-|Fmt0, Data0) -> + {F,Fmt,Data1} = field_value(Fmt0, Data0), + field_width(-F, Fmt, Data1); +field_width(Fmt0, Data0) -> + {F,Fmt,Data1} = field_value(Fmt0, Data0), + field_width(F, Fmt, Data1). + +field_width(F, Fmt, Data) when F < 0 -> + {-F,left,Fmt,Data}; +field_width(F, Fmt, Data) when F >= 0 -> + {F,right,Fmt,Data}. + +precision($.|Fmt, Data) -> field_value(Fmt, Data); +precision(Fmt, Data) -> {none,Fmt,Data}. + +field_value($*|Fmt, D|Data) when is_integer(D) -> + {D,Fmt,Data}; +field_value(C|Fmt, Data) when is_integer(C), C >= $0, C =< $9 -> + field_value(C|Fmt, Data, 0); +field_value(Fmt, Data) -> + {none,Fmt,Data}. + +field_value(C|Fmt, Data, F) when is_integer(C), C >= $0, C =< $9 -> + field_value(Fmt, Data, 10*F + (C - $0)); +field_value(Fmt, Data, F) -> %Default case + {F,Fmt,Data}. + +pad_char($.,$*|Fmt, Pad|Data) -> {Pad,Fmt,Data}; +pad_char($.,Pad|Fmt, Data) -> {Pad,Fmt,Data}; +pad_char(Fmt, Data) -> {$\s,Fmt,Data}. + +%% pcount(ControlStructs) -> Count. %% Count the number of print requests. pcount(Cs) -> - foldl(fun ({$p,_,_,_,_,_}, Acc) -> Acc+1; - ({$P,_,_,_,_,_}, Acc) -> Acc+1; + foldl(fun (#cstruct{cchar=$p}, Acc) -> Acc+1; + (#cstruct{cchar=$P}, Acc) -> Acc+1; (_, Acc) -> Acc end, 0, Cs). -%% build(FormatList, Pc, Indentation) -> Char. +%% build(ControlStruct, PrintRequestCount, Indentation) -> Char. %% Interpret the control structures. Count the number of print %% remaining and only calculate indentation when necessary. Must also %% be smart when calculating indentation for characters in format. -build({C,As,F,Ad,P,Pad}|Cs, Pc0, I) -> - S = control(C, As, F, Ad, P, Pad, I), +build(#cstruct{}=Cstruct|Cs, Pc0, I) -> + #cstruct{cchar=C,args=As,width=Width,adjust=Ad,prec=P,pad=Pad} = Cstruct, + S = control(C, As, Width, Ad, P, Pad, I), Pc1 = decr_pc(C, Pc0), if Pc1 > 0 -> S|build(Cs, Pc1, indentation(S, I)); @@ -137,29 +150,29 @@ indentation(Cs, indentation(C, I)); indentation(, I) -> I. -%% collect_cc(FormatChar, Argument) -> -%% {Control,ControlArg,FormatChar,Arg}. +%% collect_cc(Format, Data) -> +%% {Control,ControlArg,Format,Data}. %% Here we collect the argments for each control character. %% Be explicit to cause failure early. -collect_cc($w|Fmt, A|Args) -> {$w,A,Fmt,Args}; -collect_cc($p|Fmt, A|Args) -> {$p,A,Fmt,Args}; -collect_cc($W|Fmt, A,Depth|Args) -> {$W,A,Depth,Fmt,Args}; -collect_cc($P|Fmt, A,Depth|Args) -> {$P,A,Depth,Fmt,Args}; -collect_cc($s|Fmt, A|Args) -> {$s,A,Fmt,Args}; -collect_cc($e|Fmt, A|Args) -> {$e,A,Fmt,Args}; -collect_cc($f|Fmt, A|Args) -> {$f,A,Fmt,Args}; -collect_cc($g|Fmt, A|Args) -> {$g,A,Fmt,Args}; -collect_cc($b|Fmt, A|Args) -> {$b,A,Fmt,Args}; -collect_cc($B|Fmt, A|Args) -> {$B,A,Fmt,Args}; -collect_cc($x|Fmt, A,Prefix|Args) -> {$x,A,Prefix,Fmt,Args}; -collect_cc($X|Fmt, A,Prefix|Args) -> {$X,A,Prefix,Fmt,Args};
View file
_service:tar_scm:lfe-1.3.tar.gz/src/lfe_io_pretty.erl -> _service:tar_scm:lfe-2.1.1.tar.gz/src/lfe_io_pretty.erl
Changed
@@ -1,4 +1,4 @@ -%% Copyright (c) 2008-2016 Robert Virding +%% Copyright (c) 2008-2021 Robert Virding %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -18,18 +18,18 @@ -module(lfe_io_pretty). +%% The basic API. -export(term/1,term/2,term/3,term/4). +%% These might be useful somewhere else. +-export(newline/1,newline/2,last_length/1,last_length/2). --compile(export_all). +%% -compile(export_all). -import(lists, reverse/1,reverse/2,flatlength/1). -%% Define IS_MAP/1 macro for is_map/1 bif. --ifdef(HAS_MAPS). --define(IS_MAP(T), is_map(T)). --else. --define(IS_MAP(T), false). --endif. +-include("lfe.hrl"). + +-define(MAPVIND, 2). %Extra indentation of map value %% term(Sexpr , Depth , Indentation , LineLength) -> char(). %% A relatively simple pretty print function, but with some @@ -52,9 +52,6 @@ term(backquote,E, D, I, L) -> "`",term(E, D, I+1, L); term(comma,E, D, I, L) -> ",",term(E, D, I+1, L); term('comma-at',E, D, I, L) -> ",@",term(E, D, I+2, L); -term(map|MapBody, D, I, L) -> %Special case map form - Mcs = map_body(MapBody, D, I+5, L), - "(map ",Mcs,$); term(Car|_=List, D, I, L) -> %% Handle printable lists specially. case io_lib:printable_unicode_list(List) of @@ -85,14 +82,27 @@ term(Bit, D, _, _) when is_bitstring(Bit) -> bitstring(Bit, D); %First D bytes term(Map, D, I, L) when ?IS_MAP(Map) -> - %% This will return kv pairs in reverse order to from_list, but - %% this dooesn't really matter here. - Fun = fun (K, V, Acc) -> K,V|Acc end, - Mcs = map_body(maps:fold(Fun, , Map), D, I+3, L), - "#M(",Mcs,$); + %% Preserve kv pair ordering, the extra copying is trivial here. + map(Map, D, I, L); term(Other, _, _, _) -> lfe_io_write:term(Other). %Use standard LFE for rest +%% map(Map, Depth, Indentation, LineLength) -> string(). +%% Print a map butt specially handle structs. + +map(Map, D, I, L) -> + %% Preserve kv pair ordering, the extra copying is trivial here. + Mkvs = maps:to_list(Map), + case lists:keyfind('__struct__', 1, Mkvs) of + {'__struct__',Struct} -> + Skvs = lists:keydelete('__struct__', 1, Mkvs), + Scs = map_body(Skvs, D, I+3, L), + "#S(",lfe_io_write:symbol(Struct),newline(I+3),Scs,$); + false -> + Mcs = map_body(Mkvs, D, I+3, L), + "#M(",Mcs,$) + end. + %% bitstring(Bitstring, Depth) -> char() %% Print the bytes in a bitstring. Print bytes except for last which %% we add size field if not 8 bits big. @@ -307,7 +317,7 @@ indent_type('match-spec') -> 0; indent_type(_) -> none. -%% map(KVs, Depth, Indentation, LineLength). +%% map_body(KVs, Depth, Indentation, LineLength). %% map_body(KVs, CurrentLineIndent, Depth, Indentation, LineLength) %% Don't include the start and end of the map as this is called from %% differenct functions. @@ -315,44 +325,35 @@ map_body(KVs, D, I, L) -> map_body(KVs, I, D, I, L-1). -map_body(K,V|KVs, CurL, D, I, L) -> - case map_assoc(K, V, CurL, D, I, L) of +map_body(KV|KVs, CurL, D, I, L) -> + case map_assoc(KV, CurL, D, I, L) of {curr_line,KVcs,KVl} -> %Both fit on current line KVcs,map_rest(KVs, CurL+KVl, D-1, I, L); {one_line,KVcs,KVl} -> %Both fit on one line KVcs,map_rest(KVs, I+KVl, D-1, I, L); {sep_lines,Kcs,Vcs} -> %On separate lines %% Force a break after K/V split. - Kcs,newline(I, Vcs),map_rest(KVs, L, D-1, I, L) + Kcs,newline(I+?MAPVIND, Vcs),map_rest(KVs, L, D-1, I, L) end; -map_body(E, CurL, D, I, L) -> - map_last(E, CurL, D, I, L). +map_body(, _CurL, _D, _I, _L) -> . -%% map_rest(KVs, Depth, Indentation, LineLength) %% map_rest(KVs, CurrentLineIndent, Depth, Indentation, LineLength) -map_rest(KVs, D, I, L) -> - map_rest(KVs, I, D, I, L-1). - map_rest(_, _, 0, _, _) -> " ..."; %Reached our depth -map_rest(K,V|KVs, CurL, D, I, L) -> - case map_assoc(K, V, CurL+1, D, I, L) of +map_rest(KV|KVs, CurL, D, I, L) -> + case map_assoc(KV, CurL+1, D, I, L) of {curr_line,KVcs,KVl} -> %Both fit on current line $\s,KVcs,map_rest(KVs, CurL+KVl+1, D-1, I, L); {one_line,KVcs,KVl} -> %Both fit on one line newline(I, KVcs),map_rest(KVs, I+KVl, D-1, I, L); {sep_lines,Kcs,Vcs} -> %On separate lines %% Force a break after K/V split. - newline(I, Kcs),newline(I, Vcs),map_rest(KVs, L, D-1, I, L) + newline(I, Kcs),newline(I+?MAPVIND, Vcs), + map_rest(KVs, L, D-1, I, L) end; -map_rest(E, CurL, D, I, L) -> - map_last(E, CurL, D, I, L). - -%% Print any remaining element as list element. -map_last(Tail, CurL, D, I, L) -> - list_tail(Tail, CurL, D, I, L). +map_rest(, _CurL, _D, _I, _L) -> . -map_assoc(K, V, CurL, D, I, L) -> +map_assoc({K,V}, CurL, D, I, L) -> Kcs = term(K, D, 0, 99999), %Never break the line Kl = flatlength(Kcs), Vcs = term(V, D, 0, 99999), %Never break the line @@ -367,7 +368,7 @@ true -> term(K, D, I, L) end, Vs = if I+Vl < L-10 -> Vcs; - true -> term(V, D, I, L) + true -> term(V, D, I+?MAPVIND, L) end, {sep_lines,Ks,Vs} end.
View file
_service:tar_scm:lfe-1.3.tar.gz/src/lfe_io_write.erl -> _service:tar_scm:lfe-2.1.1.tar.gz/src/lfe_io_write.erl
Changed
@@ -1,4 +1,4 @@ -%% Copyright (c) 2008-2015 Robert Virding +%% Copyright (c) 2008-2020 Robert Virding %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -22,12 +22,7 @@ %% -compile(export_all). -%% Define IS_MAP/1 macro for is_map/1 bif. --ifdef(HAS_MAPS). --define(IS_MAP(T), is_map(T)). --else. --define(IS_MAP(T), false). --endif. +-include("lfe.hrl"). %% print(IoDevice, Sexpr) -> ok. %% print1(Sexpr) -> char(). @@ -48,7 +43,11 @@ "#(",list(Es, D-1),")"; term(Bit, _) when is_bitstring(Bit) -> bitstring(Bit); +term(Fun, D) when is_function(Fun) -> + function(Fun, D); term(Map, D) when ?IS_MAP(Map) -> map(Map, D); +term(Pid, D) when is_pid(Pid) -> + "#Pid" ++ io_lib:write(Pid, D); term(Other, D) -> %Use standard Erlang for rest io_lib:write(Other, D). @@ -81,6 +80,22 @@ <<B:N>> = Bits, io_lib:format("(~w (size ~w))", B,N). +%% function(Function, Depth) -> Chars +%% We want it all so give it lots of depth! + +function(Fun, _) -> + {module,M} = erlang:fun_info(Fun, module), + {name,F} = erlang:fun_info(Fun, name), + {arity,A} = erlang:fun_info(Fun, arity), + case erlang:fun_info(Fun, type) of + {type,external} -> + term(function,M,F,A, -1); + _ -> + %% Having a little bit of fun. + lists:droplast(erlang:fun_to_list(Fun)), + "/",integer_to_list(A),">" + end. + %% list(List, Depth) -> Chars. %% Print the elements in a list. We handle the empty list and depth=0.
View file
_service:tar_scm:lfe-1.3.tar.gz/src/lfe_lib.erl -> _service:tar_scm:lfe-2.1.1.tar.gz/src/lfe_lib.erl
Changed
@@ -1,4 +1,4 @@ -%% Copyright (c) 2008-2016 Robert Virding +%% Copyright (c) 2008-2020 Robert Virding %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -19,7 +19,8 @@ -module(lfe_lib). %% General library functions. --export(is_symb/1,is_symb_list/1,is_proper_list/1,is_doc_string/1). +-export(is_symb/1,is_symb_list/1,is_posint_list/1, + is_proper_list/1,is_doc_string/1). -export(proc_forms/3,proc_forms/4). @@ -42,6 +43,11 @@ is_symb_list() -> true; is_symb_list(_) -> false. %Might not be a proper list +is_posint_list(I|Is) when is_integer(I), I >= 0 -> + is_posint_list(Is); +is_posint_list() -> true; +is_posint_list(_) -> false. + is_proper_list(_|Ss) -> is_proper_list(Ss); is_proper_list() -> true; is_proper_list(_) -> false. @@ -139,32 +145,68 @@ format_stacktrace(St1, Skip, Format). %% format_reason(Error, Indentation) -> DeepCharList. -%% Format an error giving a little better information. - -format_reason(badarg, _I) -> <<"bad argument">>; -format_reason(badarith, _I) -> <<"error in arithmetic expression">>; +%% Format an error giving a little better information. Explicitly +%% handle errors known from ERTS here, anything is assumed to come +%% from lfe_eval. + +%% The ERTS exit codes. +format_reason(badarg, _I) -> + <<"bad argument">>; +format_reason({badarg,V}, I) -> + format_value(V, <<"bad argument ">>, I); +format_reason(badarith, _I) -> + <<"error in arithmetic expression">>; +format_reason({badarity,{Fun,As}}, _I) + when is_function(Fun) -> + %% Only the arity is displayed, not the arguments As. + lfe_io:format1(<<"~s called with ~s">>, + format_fun(Fun),argss(length(As))); +format_reason({badfun,Term}, I) -> + format_value(Term, <<"bad function ">>, I); format_reason({badmatch,V}, I) -> - lfe_io:format1(<<"no match of value ~.*P">>, I+18,V,10); -format_reason(function_clause, _I) -> <<"no function clause matching">>; + format_value(V, <<"no match of value ">>, I); format_reason({case_clause,V}, I) -> - lfe_io:format1(<<"no case clause matching ~.*P">>, I+24,V,10); -format_reason(if_clause, _I) -> <<"no if clause matching">>; -format_reason(undef, _I) -> <<"undefined function">>; -%% Some LFE eval specific errors. -format_reason({unbound_symb,S}, _I) -> - lfe_io:format1(<<"symbol ~w is unbound">>, S); -format_reason(illegal_guard, _I) -> <<"illegal guard">>; -format_reason({undefined_func,{F,A}}, _I) -> - lfe_io:format1(<<"undefined function ~w/~w">>, F,A); -format_reason(if_expression, _I) -> <<"non-boolean if test">>; -format_reason({illegal_pattern,Pat}, _I) -> - lfe_io:format1(<<"illegal pattern ~w">>, Pat); -format_reason({illegal_literal,Lit}, I) -> - lfe_io:format1(<<"illegal literal value ~.*P">>, I+22,Lit,10); -format_reason(bad_arity, _I) -> <<"arity mismatch">>; -%% Default catch-all -format_reason(Error, I) -> %Default catch-all - lfe_io:prettyprint1(Error, 10, I). + %% "there is no case clause with a true guard sequence and a + %% pattern matching..." + format_value(V, <<"no case clause matching ">>, I); +format_reason(function_clause, _I) -> + <<"no function clause matching">>; +format_reason(if_clause, _I) -> + <<"no if clause matching">>; +format_reason(noproc, _I) -> <<"no such process or port">>; +format_reason(notalive, _I) -> + <<"the node cannot be part of a distributed system">>; +format_reason(system_limit, _I) -> + <<"a system limit has been reached">>; +format_reason(timeout_value, _I) -> + <<"bad receive timeout value">>; +format_reason({try_clause,V}, I) -> + %% "there is no try clause with a true guard sequence and a + %% pattern matching..." + format_value(V, <<"no try clause matching ">>, I); +format_reason(undef, _I) -> + <<"undefined function">>; +%% We now pass the buck to lfe_eval. +format_reason(Error, _) -> + lfe_eval:format_error(Error). + +argss(0) -> <<"no arguments">>; +argss(1) -> <<"one argument">>; +argss(N) -> lfe_io:format1(<<"~w arguments">>, N). + +format_fun(Fun) when is_function(Fun) -> + {module,M} = erlang:fun_info(Fun, module), + %% {name,F} = erlang:fun_info(Fun, name), + {arity,A} = erlang:fun_info(Fun, arity), + case erlang:fun_info(Fun, type) of + {type,local} when M =:= lfe_eval -> + lfe_io:format1(<<"interpreted function with arity ~w">>, A); + _ -> lfe_io:print1(Fun) + end. + +format_value(Val, ErrStr, I) -> + Sz = I + iolist_size(ErrStr), + lfe_io:format1(<<"~s~.*P">>, ErrStr,Sz,Val,10). %% format_stacktrace(Stacktrace, SkipFun, FormatFun) -> DeepCharList. %% Format a stacktrace. SkipFun is used to trim the end of stack;
View file
_service:tar_scm:lfe-1.3.tar.gz/src/lfe_lint.erl -> _service:tar_scm:lfe-2.1.1.tar.gz/src/lfe_lint.erl
Changed
@@ -1,4 +1,4 @@ -%% Copyright (c) 2008-2017 Robert Virding +%% Copyright (c) 2008-2021 Robert Virding %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -16,6 +16,11 @@ %% Author : Robert Virding %% Purpose : Lisp Flavoured Erlang syntax checker. +%%% We get a lot help here from the Erlang linter as our code is +%%% passed on into it when the erlng code is compiled. This means that +%%% if we miss anything it will catch it. How much do we really needt +%%% to do here? + %%% In a fun argument where when matching a binary we import the size %%% of bitseg as a variable from the environment not just from earlier %%% segments. No other argument variables are imported. @@ -27,120 +32,169 @@ %% -compile(export_all). --import(lists, member/2,sort/1,all/2,foldl/3,foldr/3,foreach/2,mapfoldl/3). --import(ordsets, add_element/2,from_list/1,is_element/2, - union/1,union/2,intersection/2,subtract/2). - -include("lfe_comp.hrl"). - -%% We do a lot of quoting! --define(Q(E), quote,E). --define(BQ(E), backquote,E). --define(C(E), comma,E). --define(C_A(E), 'comma-at',E). - --record(lint, {module=, %Module name - mline=0, %Module definition line - exps=orddict:new(), %Exports - imps=, %Imports - pref=, %Prefixes - funcs=, %Defined functions - types=, %Known types - specs=, %Known func specs - env=, %Top-level environment - func=, %Current function - file="nofile", %File name - opts=, %Compiler options - errors=, %Errors - warnings= %Warnings - }). +-include("lfe.hrl"). + +-record(lfe_lint, {module=, %Module name + mline=0, %Module definition line + exports=orddict:new(), %Exported function-line + imports=orddict:new(), %Imported function-{module,func} + aliases=orddict:new(), %Module-alias + onload=, %Onload + funcs=orddict:new(), %Defined function-line + types=, %Known types + texps=orddict:new(), %Exported types + specs=, %Known func specs + records=orddict:new(), %Known record definitions + struct=undefined, %Struct definition + env=, %Top-level environment + func=, %Current function + file="no file", %File name + opts=, %Compiler options + errors=, %Errors + warnings= %Warnings + }). %% Errors. -format_error({bad_mdef,D}) -> - lfe_io:format1("bad module definition: ~w", D); -format_error(bad_extends) -> "bad extends"; -format_error(bad_funcs) -> "bad function list"; -format_error(bad_body) -> "bad body"; -format_error(bad_clause) -> "bad clause"; -format_error(bad_guard) -> "bad guard"; +%% Module definition. +format_error({bad_module_def,D}) -> + %% This can handle both atom and string error value. + lfe_io:format1(<<"bad ~s in module definition">>, D); +format_error({bad_attribute,A}) -> + lfe_io:format1(<<"bad ~w attribute">>, A); +format_error({bad_meta_def,M}) -> + lfe_io:format1(<<"bad ~w metadata definition">>, M); +%% Forms and code. +format_error({bad_body_def,Form}) -> + lfe_io:format1(<<"bad body in ~w">>, Form); +format_error(bad_guard_def) -> "bad guard definition"; format_error(bad_args) -> "bad argument list"; format_error(bad_gargs) -> "bad guard argument list"; -format_error(bad_alias) -> "bad pattern alias"; -format_error(bad_arity) -> "head arity mismatch"; -format_error({bad_attribute,A}) -> - lfe_io:format1("bad attribute: ~w", A); -format_error({bad_meta,M}) -> - lfe_io:format1("bad metadata: ~w", M); -format_error({bad_form,Type}) -> - lfe_io:format1("bad ~w form", Type); -format_error({bad_gform,Type}) -> - lfe_io:format1("bad ~w guard form", Type); -format_error({bad_pat,Type}) -> - lfe_io:format1("bad ~w pattern", Type); -format_error({unbound_symb,S}) -> - lfe_io:format1("symbol ~w unbound", S); -format_error({undefined_func,F}) -> - lfe_io:format1("function ~w undefined", F); +format_error(bad_pat_alias) -> "bad pattern alias"; +format_error(bad_head_arity) -> "function head arity mismatch"; +format_error({bad_form,Form}) -> + lfe_io:format1(<<"bad ~w form">>, Form); +format_error({bad_guard_form,Form}) -> + lfe_io:format1(<<"bad ~w guard form">>, Form); +format_error({bad_pattern,Pat}) -> + lfe_io:format1(<<"bad ~w pattern">>, Pat); +format_error({unbound_symbol,S}) -> + lfe_io:format1(<<"symbol ~w is unbound">>, S); +format_error({undefined_function,{F,Ar}}) -> + lfe_io:format1("function ~w/~w undefined", F,Ar); format_error({multi_var,S}) -> lfe_io:format1("variable ~w multiply defined", S); -format_error({redef_fun,F}) -> - lfe_io:format1("redefining function ~w", F); +%% Functions, imports, exports, on_loads and aliases. +format_error({redefine_function,{F,Ar}}) -> + lfe_io:format1("function ~w/~w already defined", F,Ar); format_error({bad_fdef,F}) -> lfe_io:format1("bad definition of function ~w", F); +format_error({reimport_function,{F,Ar},M1,M2}) -> + lfe_io:format1(<<"importing ~w/~w from ~w, already imported from ~w">>, + F,Ar,M1,M2); +format_error({define_imported_function,{F,Ar}}) -> + lfe_io:format1(<<"defining imported function ~w/~w">>, F,Ar); +format_error({undefined_onload_function,{F,Ar}}) -> + lfe_io:format1("on_load function ~w/~w undefined", F,Ar); +format_error({redefine_module_alias,A}) -> + lfe_io:format1(<<"redefining ~w module alias">>, A); +format_error({circular_module_alias,A}) -> + lfe_io:format1(<<"circular module alias for ~w">>, A); +%% Others format_error({illegal_literal,Lit}) -> - lfe_io:format1("illegal literal value ~w", Lit); + lfe_io:format1(<<"illegal literal value ~w">>, Lit); format_error({illegal_pattern,Pat}) -> - lfe_io:format1("illegal pattern ~w", Pat); -format_error(illegal_guard) -> "illegal guard"; + lfe_io:format1(<<"illegal pattern ~w">>, Pat); +format_error(illegal_guard) -> <<"illegal guard expression">>; format_error({illegal_mapkey,Key}) -> - lfe_io:format1("illegal map key ~w", Key); -format_error({undefined_bittype,S}) -> - lfe_io:format1("bit type ~w undefined", S); -format_error(bittype_unit) -> - "bit unit size can only be specified together with size"; + lfe_io:format1(<<"illegal map key ~w">>, Key); format_error(illegal_bitseg) -> "illegal bit segment"; format_error(illegal_bitsize) -> "illegal bit size"; format_error({deprecated,What}) -> - lfe_io:format1("deprecated: ~s", What); + lfe_io:format1("~s is deprecated", What); format_error(unknown_form) -> "unknown form"; -format_error({bad_record,R}) -> - lfe_io:format1("bad record definition: ~w", R); +%% Try-catches. +format_error({illegal_stacktrace,S}) -> + lfe_io:format1(<<"stacktrace ~w must be unbound variable">>, S); +format_error({illegal_exception,E}) -> + lfe_io:format1(<<"illegal exception ~w">>, E); +%% Records. +format_error({bad_record_def,Name}) -> + lfe_io:format1(<<"bad definition of record ~w">>, Name); +format_error({bad_record_name,Name}) -> + lfe_io:format1(<<"bad record name ~w">>, Name); +format_error({bad_record_field,Name,Field}) -> + lfe_io:format1(<<"bad field ~w in record ~w">>, Field,Name); +format_error({redefine_record,Name}) -> + lfe_io:format1(<<"record ~w already defined">>, Name); +format_error({missing_record_field_value,Name,Field}) -> + lfe_io:format1(<<"missing value to field ~w in record ~w">>,Field,Name); +%% Structs. +format_error(redefine_struct) -> + <<"struct already defined">>; +format_error(bad_struct_def) -> + <<"bad definition of struct">>; +format_error({bad_struct_def,Name}) -> + lfe_io:format1(<<"bad definition of struct ~w">>, Name); +format_error({bad_struct_field,Field}) -> + lfe_io:format1(<<"bad field ~w in struct">>, Field); +%% format_error({bad_struct_field,Name,Field}) -> +%% lfe_io:format1(<<"bad field ~w in struct ~w">>, Field,Name); +format_error({missing_struct_field_value,Name,Field}) -> + lfe_io:format1(<<"missing value to field ~w in struct ~w">>,Field,Name); +%% These are also used in lfe_eval. +format_error({undefined_record,Name}) -> + lfe_io:format1(<<"record ~w undefined">>, Name); +format_error({undefined_record_field,Name,Field}) -> + lfe_io:format1(<<"field ~w undefined in record ~w">>, Field,Name); +format_error({undefined_struct,Name}) ->
View file
_service:tar_scm:lfe-1.3.tar.gz/src/lfe_macro.erl -> _service:tar_scm:lfe-2.1.1.tar.gz/src/lfe_macro.erl
Changed
@@ -1,4 +1,4 @@ -%% Copyright (c) 2008-2016 Robert Virding +%% Copyright (c) 2008-2021 Robert Virding %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -27,18 +27,15 @@ -export(expand_expr/2,expand_expr_1/2,expand_expr_all/2). %% These work on list of forms in "file format". --export(expand_forms/4). -export(expand_form_init/2,expand_form_init/3, expand_form/4,expand_fileform/3). +-export(expand_fileforms/3,expand_fileforms/4). %% For creating the macro expansion state. -export(default_state/2,default_state/3). -export(format_error/1). --export(mbe_syntax_rules_proc/4,mbe_syntax_rules_proc/5, - mbe_match_pat/3,mbe_get_bindings/3,mbe_expand_pattern/3). - %% -compile(export_all). -import(lfe_env, new/0,add_vbinding/3,is_vbound/2, @@ -48,24 +45,20 @@ -import(lists, any/2,all/2,map/2,foldl/3,foldr/3,mapfoldl/3, reverse/1,reverse/2,member/2,concat/1). +-include("lfe.hrl"). -include("lfe_comp.hrl"). -include("lfe_macro.hrl"). -%% Define IS_MAP/1 macro for is_map/1 bif. --ifdef(HAS_MAPS). --define(IS_MAP(T), is_map(T)). --else. --define(IS_MAP(T), false). --endif. - -%% Errors +%% Errors we get, generally in the predefined macros. format_error({bad_form,Type}) -> - lfe_io:format1("bad form: ~w", Type); + lfe_io:format1(<<"bad form: ~w">>, Type); format_error({bad_env_form,Type}) -> - lfe_io:format1("bad environment form: ~w", Type); + lfe_io:format1(<<"bad environment form: ~w">>, Type); format_error({expand_macro,Call,Error}) -> %% Can be very big so only print limited depth. - lfe_io:format1("error expanding ~P: ~P", Call,10,Error,10). + lfe_io:format1(<<"error expanding ~P:\n ~P">>, Call,10,Error,10); +format_error(Error) -> + lfe_io:format1(<<"macro expansion error: ~P\n">>, Error,10). %% expand_expr(Form, Env) -> {yes,Exp} | no. %% expand_expr_1(Form, Env) -> {yes,Exp} | no. @@ -104,21 +97,14 @@ {Ef,_} = exp_form(F, Env, default_state(true, false)), Ef. -%% expand_forms(FileForms, Env, Deep, Keep) -> -%% {ok,FileForms,Env,Warnings} | {error,Errors,Warnings}. -%% Collect macro definitions in file forms, completely expand all -%% macros and only keep all functions. +%% expand_form_init(Deep, Keep) -> State. +%% expand_form_init(CompInfo, Deep, Keep) -> State. -expand_forms(Fs, Env, Deep, Keep) -> - St = default_state(Deep, Keep), - do_forms(Fs, Env, St). +expand_form_init(Deep, Keep) -> + default_state(Deep, Keep). -do_forms(Fs0, Env0, St0) -> - {Fs1,Env1,St1} = pass_fileforms(Fs0, Env0, St0), - case St1#mac.errors of - -> {ok,Fs1,Env1,St1#mac.warnings}; %No errors - Es -> {error,Es,St1#mac.warnings} - end. +expand_form_init(Ci, Deep, Keep) -> + default_state(Ci, Deep, Keep). default_state(Deep, Keep) -> #mac{deep=Deep,keep=Keep,line=1,file="-no-file-",opts=,ipath="."}. @@ -126,19 +112,11 @@ default_state(#cinfo{file=File,opts=Os,ipath=Is}, Deep, Keep) -> #mac{deep=Deep,keep=Keep,line=1,file=File,opts=Os,ipath=Is}. -%% expand_form_init(Deep, Keep) -> State. -%% expand_form_init(CompInfo, Deep, Keep) -> State. -%% expand_form(Form, Line, Env, State) -> {Form,Env,State}. -%% expand_fileform(Form, Env, State) -> {Form,Env,State}. +%% expand_form(Form, Line, Env, MacState) -> {Form,Env,MacState}. +%% expand_fileform(FileForm, Env, MacState) -> {FileForm,Env,MacState}. %% Collect macro definitions in a (file)form, completely expand all %% macros and only keep all functions. -expand_form_init(Deep, Keep) -> - default_state(Deep, Keep). - -expand_form_init(Ci, Deep, Keep) -> - default_state(Ci, Deep, Keep). - expand_form(F0, L, E0, St0) -> {F1,E1,St1} = pass_form(F0, E0, St0#mac{line=L}), return_status(F1, E1, St1). @@ -152,6 +130,27 @@ return_status(_, _, #mac{errors=Es,warnings=Ws}=St) -> {error,Es,Ws,St}. +%% expand_fileforms(FileForms, Env, MacState) -> +%% expand_fileforms(FileForms, Env, Deep, Keep) -> +%% {ok,FileForms,Env,Warnings} | {error,Errors,Warnings}. +%% Collect macro definitions in file forms, completely expand all +%% macros and only keep all functions. This is intended to process a +%% whole file so the end macro state is not returned. + +expand_fileforms(Fs, Env, St) -> + do_forms(Fs, Env, St). + +expand_fileforms(Fs, Env, Deep, Keep) -> + St = default_state(Deep, Keep), + do_forms(Fs, Env, St). + +do_forms(Fs0, Env0, St0) -> + {Fs1,Env1,St1} = pass_fileforms(Fs0, Env0, St0), + case St1#mac.errors of + -> {ok,Fs1,Env1,St1#mac.warnings}; %No errors + Es -> {error,Es,St1#mac.warnings} + end. + %% pass_fileforms(FileForms, Env, State) -> {FileForms,Env,State}. %% pass_forms(Forms, Env, State) -> {Forms,Env,State}. %% Pass over a list of fileforms/forms collecting and removing all macro @@ -179,6 +178,18 @@ pass_form('eval-when-compile'|Efs0, Env0, St0) -> {Efs1,Env1,St1} = pass_ewc(Efs0, Env0, St0), {'eval-when-compile'|Efs1,Env1,St1}; +pass_form('include-file',File, Env, St0) -> + case lfe_macro_include:file(File, Env, St0) of + {yes,Exp,St1} -> pass_form(Exp, Env, St1); + {error,St1} -> + {'progn',Env,St1} + end; +pass_form('include-lib',Lib, Env, St0) -> + case lfe_macro_include:lib(Lib, Env, St0) of + {yes,Exp,St1} -> pass_form(Exp, Env, St1); + {error,St1} -> + {'progn',Env,St1} + end; pass_form('define-macro'|Def=M, Env0, St0) -> case pass_define_macro(Def, Env0, St0) of {yes,Env1,St1} -> @@ -359,18 +370,72 @@ exp_normal_core(binary, As, Env, St); exp_form(map|As, Env, St) -> exp_normal_core(map, As, Env, St); +exp_form(msiz|As, Env, St) -> + exp_normal_core(msiz, As, Env, St); exp_form(mref|As, Env, St) -> exp_normal_core(mref, As, Env, St); exp_form(mset|As, Env, St) -> exp_normal_core(mset, As, Env, St); exp_form(mupd|As, Env, St) -> exp_normal_core(mupd, As, Env, St); +exp_form(mrem|As, Env, St) -> + exp_normal_core(mrem, As, Env, St); +exp_form('map-size'|As, Env, St) -> + exp_normal_core('map-size', As, Env, St); exp_form('map-get'|As, Env, St) -> exp_normal_core('map-get', As, Env, St); exp_form('map-set'|As, Env, St) -> exp_normal_core('map-set', As, Env, St); exp_form('map-update'|As, Env, St) -> exp_normal_core('map-update', As, Env, St); +exp_form('map-remove'|As, Env, St) -> + exp_normal_core('map-remove', As, Env, St); +%% Record special forms. Note that these are used for both the +%% compiler as well as the evaluator so we can't do too much here. +exp_form('define-record',Name,Fds, Env, St0) -> + {Efds,St1} = exp_rec_fields(Name, Fds, Env, St0), + {'define-record',Name,Efds,St1}; +exp_form('record',Name|Args, Env, St0) -> + {Eas,St1} = exp_tail(Args, Env, St0), + {'record',Name|Eas,St1}; +%% make-record has been deprecated but we sill accept it for now. +exp_form('make-record',Name|Args, Env, St0) -> + {Eas,St1} = exp_tail(Args, Env, St0), + {'make-record',Name|Eas,St1}; +exp_form('is-record',E,Name, Env, St0) -> + {Ee,St1} = exp_form(E, Env, St0), + {'is-record',Ee,Name,St1}; +exp_form('record-index',Name,F, _, St) -> + {'record-index',Name,F,St}; +exp_form('record-field',E,Name,F, Env, St0) -> + {Ee,St1} = exp_form(E, Env, St0), + {'record-field',Ee,Name,F,St1}; +exp_form('record-update',E,Name|Args, Env, St0) ->
View file
_service:tar_scm:lfe-1.3.tar.gz/src/lfe_macro.hrl -> _service:tar_scm:lfe-2.1.1.tar.gz/src/lfe_macro.hrl
Changed
@@ -1,4 +1,4 @@ -%% Copyright (c) 2013-2016 Robert Virding +%% Copyright (c) 2013-2020 Robert Virding %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -16,12 +16,6 @@ %% Author : Robert Virding %% Purpose : Lisp Flavoured Erlang macro expander. -%% We do a lot of quoting! --define(Q(E), quote,E). --define(BQ(E), backquote,E). --define(C(E), comma,E). --define(C_A(E), 'comma-at',E). - %% Macro expander state. -record(mac, {deep=true, %Deep expand everything keep=true, %Keep all forms
View file
_service:tar_scm:lfe-1.3.tar.gz/src/lfe_macro_export.erl -> _service:tar_scm:lfe-2.1.1.tar.gz/src/lfe_macro_export.erl
Changed
@@ -1,4 +1,4 @@ -%% Copyright (c) 2016 Robert Virding +%% Copyright (c) 2016-2022 Robert Virding %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -27,7 +27,7 @@ %% also enter all the functions and variables defined inside ewc so %% they can be reached from these macros when the L-E-E-M function is %% compiled. We do NOT need to save the ewc macros as they will -%% accessible when he module is compiled. +%% accessible when the module is compiled. %% %% The macros will be expanded in the context of the module when it is %% later compiled and not in the context of the calling module. This @@ -57,18 +57,12 @@ %%-compile(export_all). --include("lfe_comp.hrl"). +-include("lfe.hrl"). -export(module/2). -import(lists, reverse/1,reverse/2,member/2,filter/2). -%% We do a lot of quoting! --define(Q(E), quote,E). --define(BQ(E), backquote,E). --define(C(E), comma,E). --define(C_A(E), 'comma-at',E). - -define(NOMETA, ). %Empty documentation %% We need these variables to have a funny name. @@ -76,8 +70,10 @@ -define(ARGSVAR, '|- CALL ARGS -|'). %% Define the macro data. --record(umac, {mline=,expm=,env=, - leem=false,huf=false %Do we have leem and huf? +-record(umac, {mline=, %expand-macro on line + expm=, %Macros to export + env=, %LFE env to store macros + uleem=false %Do we have user defined LEEM? }). %% module(ModuleForms, CompState) -> {ModuleForms,CompState}. @@ -86,18 +82,17 @@ module(Mdef|Fs, Cst) -> Mst = collect_macros(Fs, #umac{env=lfe_env:new()}), - %% io:format("m: ~p\n", Umac), module(Mdef, Fs, Mst, Cst). -module({'define-module',Name,Meta,Atts,L}, Fs0, Mst0, Cst) -> +module({'define-module',Name,Meta,Atts,L}, Fs, Mst0, Cst) -> Mst1 = collect_attrs(Atts, Mst0#umac{mline=L}), - Fs1 = add_huf(L, Fs0), - Umac = build_user_macro(Mst1), + Emac = build_exported_macro(Mst1), %% We need to export the expansion function but leave the rest. - Exp = export,'LFE-EXPAND-EXPORTED-MACRO',3, - '$handle_undefined_function',2, + Exp = export,'LFE-EXPAND-EXPORTED-MACRO',3, Md1 = {'define-module',Name,Meta,Exp|Atts,L}, - {Md1|Fs1 ++ Umac,Cst}. + %% io:format("m: ~p\n", {Md1,Fs,Emac}), + %% Put export-macro last so it can find all macros. + {Md1|Fs ++ Emac,Cst}. collect_macros(Fs, Mst) -> lists:foldl(fun collect_macro/2, Mst, Fs). @@ -110,12 +105,10 @@ collect_macro({'extend-module',_,Atts,_}, Mst) -> collect_attrs(Atts, Mst); collect_macro({'define-function',Name,_,Def,_}, Mst) -> - %% Check for LFE-EXPAND-EXPORTED-MACRO and $handle_undefined_function. + %% Check for user defined LFE-EXPAND-EXPORTED-MACRO. case {Name,function_arity(Def)} of {'LFE-EXPAND-EXPORTED-MACRO',3} -> - Mst#umac{leem=true}; - {'$handle_undefined_function',2} -> - Mst#umac{huf=true}; + Mst#umac{uleem=true}; _ -> Mst %Ignore other functions end; collect_macro(_, Mst) -> Mst. %Ignore everything else @@ -157,7 +150,7 @@ %% exported_macro(Name, State) -> true | false. add_exports(all, _) -> all; -add_exports(_, all) -> all; +add_exports(_, all) -> all; %Note we get a list of macros! add_exports(Old, More) -> ordsets:union(Old, lists:usort(More)). @@ -165,15 +158,15 @@ exported_macro(Name, #umac{expm=Expm}) -> member(Name, Expm). -%% build_user_macro(MacroState) -> UserMacFunc. +%% build_exported_macro(MacroState) -> ExportedMacFunc. %% Take the forms in the eval-when-compile and build the %% LFE-EXPAND-EXPORTED-MACRO function. In this version we expand the %% macros are compile time. -build_user_macro(#umac{leem=true}) -> ; %Already have LEEM -build_user_macro(#umac{mline=L,expm=}) -> %No macros to export - {empty_leum(),L}; -build_user_macro(#umac{mline=ModLine,env=Env}=Mst) -> +build_exported_macro(#umac{uleem=true}) -> ; %Already have user defined LEEM +build_exported_macro(#umac{mline=L,expm=}) -> %No macros to export + {empty_leem(),L}; +build_exported_macro(#umac{mline=ModLine,env=Env}=Mst) -> Vfun = fun (N, V, Acc) -> N,V|Acc end, Sets = lfe_env:fold_vars(Vfun, , Env), %% Collect the local functions. @@ -193,7 +186,7 @@ end, %% Get the macros to export as case clauses. LEEM = case lfe_env:fold_macros(Mfun, , Env) of - -> empty_leum(); %No macros to export + -> empty_leem(); %No macros to export Macs -> %% Build case, flet and let. Case = 'case',?NAMEVAR|Macs ++ '_',?Q(no), @@ -204,7 +197,7 @@ end, {LEEM,ModLine}. -empty_leum() -> +empty_leem() -> 'define-function','LFE-EXPAND-EXPORTED-MACRO',?NOMETA, lambda,'_','_','_',?Q(no). @@ -231,30 +224,3 @@ Args,W,tuple,?Q(yes),progn|Body; macro_clause(Args, Body) -> Args,tuple,?Q(yes),progn|Body. - -%% add_huf(ModLine, Forms) -> Forms. -%% Add the $handle_undefined_function/2 function to catch run-time -%% macro calls. Scan through forms to check if there is an -%% $handle_undefined_function/2 function already defined. If so use -%% that as default when not a macro, otherwise just generate the -%% standard undef error. - -add_huf(L, {'define-function','$handle_undefined_function',Meta,Def,Lf}=F|Fs) -> - case function_arity(Def) of - 2 -> {make_huf(Meta, Def),Lf}|Fs; %Found the right $huf - _ -> F|add_huf(L, Fs) %Keep going - end; -add_huf(L, F|Fs) -> - F|add_huf(L, Fs); -add_huf(L, ) -> %No $huf, so make one. - %% Use the default undef exception handler. - Excep = lambda,a,b, - ':',error_handler,raise_undef_exception,'MODULE',a,b, - {make_huf(, Excep),L}. - -make_huf(Meta, Huf) -> - 'define-function','$handle_undefined_function',Meta, - lambda,f,as, - 'case','LFE-EXPAND-EXPORTED-MACRO',f,as,':',lfe_env,new, - tuple,?Q(yes),exp,':',lfe_eval,expr,exp, - ?Q(no),funcall,Huf,f,as.
View file
_service:tar_scm:lfe-1.3.tar.gz/src/lfe_macro_include.erl -> _service:tar_scm:lfe-2.1.1.tar.gz/src/lfe_macro_include.erl
Changed
@@ -1,4 +1,4 @@ -%% Copyright (c) 2013-2017 Robert Virding +%% Copyright (c) 2013-2020 Robert Virding %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -29,6 +29,7 @@ %%-compile(export_all). +-include("lfe.hrl"). -include("lfe_macro.hrl"). %% Test function to inspect output of parsing functions. @@ -44,102 +45,139 @@ end. %% Errors. +format_error({bad_form,Type}) -> + lfe_io:format1(<<"bad ~w form">>, Type); +format_error({no_include,T,F}) -> + io_lib:format(<<"can't find include ~w ~ts">>, T,F); format_error({notrans_function,F,A}) -> - io_lib:format("unable to translate function ~w/~w", F,A); + lfe_io:format1(<<"unable to translate function ~w/~w">>, F,A); format_error({notrans_record,R}) -> - io_lib:format("unable to translate record ~w", R); + lfe_io:format1(<<"unable to translate record ~w">>, R); format_error({notrans_type,T}) -> - io_lib:format("unable to translate type ~w", T); + lfe_io:format1(<<"unable to translate type ~w">>, T); format_error({notrans_macro,M}) -> - io_lib:format("unable to translate macro ~w", M). + lfe_io:format1(<<"unable to translate macro ~w">>, M); +%% File errors are passed on. +format_error({file_error,E}) -> + file:format_error(E). +%% add_error(Error, State) -> State. +%% add_error(Line, Error, State) -> State. %% add_warning(Warning, State) -> State. %% add_warning(Line, Warning, State) -> State. +%% Add errors and warnings to the state + +add_error(E, St) -> add_error(St#mac.line, E, St). + +add_error(L, E, St) -> + St#mac{errors=St#mac.errors ++ {L,?MODULE,E}}. add_warning(W, St) -> add_warning(St#mac.line, W, St). add_warning(L, W, St) -> St#mac{warnings=St#mac.warnings ++ {L,?MODULE,W}}. -%% file(FileName, Env, MacState) -> -%% {yes,(progn ...),MacState} | {error,Error}. +%% file(FileName, Env, MacState) -> +%% {yes,(progn ...),MacState} | {error,MacState}. %% Expand the (include-file ...) macro. This is a VERY simple %% include file macro! We just signal errors. -file(Body, _, #mac{ipath=Path}=St0) -> - case include_name(Body) of +file(IncFile, _, #mac{ipath=Path}=St0) -> + case include_name(IncFile) of {ok,Name} -> case path_read_file(Path, Name, St0) of - {ok,Fs,St1} -> {yes,'progn'|Fs,St1}; - {error,E} -> error(E); - not_found -> error(enoent) + {ok,Forms,St1} -> {yes,'progn'|Forms,St1}; + {error,St1} -> {error,St1}; + not_found -> + {error,add_error({no_include,file,Name}, St0)} end; - {error,E} -> error(E) + {error,_} -> + {error,add_error({bad_form,'include-file'}, St0)} end. -%% lib(FileName, Env, MacState) -> -%% {yes,(progn ...),MacState} | {error,Error}. -%% Expand the (include-lib ...) macro. This is a VERY simple include -%% lib macro! First try to include the file directly else assume -%% first directory name is a library name. We just signal errors. +%% lib(FileName, Env, MacState) -> +%% {yes,(progn ...),MacState} | {error,MacState}. +%% Expand the (include-lib ...) macro. We do the same as epp so we +%% first test if we can find the file through the normal search path, +%% if not we assume that the first directory name is a library name, +%% find its true directory and try with that. -lib(Body, _, St0) -> - case include_name(Body) of +lib(IncFile, _, #mac{ipath=Path}=St0) -> + case include_name(IncFile) of {ok,Name} -> - case path_read_file(St0#mac.ipath, Name, St0) of - {ok,Fs,St1} -> {yes,'progn'|Fs,St1}; - {error,E} -> error(E); %Found contained error - not_found -> %File not found - case lib_file_name(Name) of - {ok,Lfile} -> - case read_file(Lfile, St0) of - {ok,Fs,St1} -> {yes,'progn'|Fs,St1}; - {error,E} -> error(E) - end; - {error,_} -> error(badarg) + case path_read_file(Path, Name, St0) of + {ok,Forms,St1} -> + {yes,'progn'|Forms,St1}; + {error,St1} -> {error,St1}; + not_found -> + case lib_read_file(Name, St0) of + {ok,Forms,St1} -> {yes,'progn'|Forms,St1}; + {error,St1} -> {error,St1}; + not_found -> + {error,add_error({no_include,lib,Name}, St0)} end end; - {error,E} -> error(E) + {error,_} -> + {error,add_error({bad_form,'include-lib'}, St0)} end. -%% path_read_file(Path, Name, State) -> {ok,Forms,State} | {error,E} | error. -%% Step down the path trying to read the file. We first test if we -%% can open it, if so then this the file we use, if not we go on. +%% include_name(FileName) -> bool(). +%% Gets the file name from the include-XXX FileName. -path_read_file(P|Ps, Name, St) -> - File = filename:join(P, Name), - case file:open(File, read,raw) of %Test if we can open the file - {ok,F} -> - file:close(F), %Close it again - read_file(File, St); - {error,_} -> - path_read_file(Ps, Name, St) - end; -path_read_file(, _, _) -> %Couldn't find/open the file - not_found. +include_name(Name) -> + try + {ok,lists:flatten(unicode:characters_to_list(Name, utf8))} + catch + _:_ -> {error,badarg} +end. -%% include_name(Body) -> bool(). -%% Gets the file name from the include-XXX body. +%% path_read_file(Path, Name, State) -> +%% {ok,Forms,State} | {error,State} | not_found. +%% Step down the path trying to read the file. -include_name(Name) -> - case io_lib:char_list(Name) of - true -> {ok,Name}; - false -> {error,badarg} - end; -include_name(_) -> {error,badarg}. +path_read_file(Path, Name, St) -> + case file:path_open(Path, Name, read,raw) of + {ok,F,Pname} -> + file:close(F), %Close it again + read_file(Pname, St); %Read it + {error,_} -> not_found %Not found + end. %% lib_file_name(LibPath) -> {ok,LibFileName} | {error,Error}. %% Construct path to true library file. -lib_file_name(Lpath) -> - Lname|Rest = filename:split(Lpath), - case code:lib_dir(list_to_atom(Lname)) of - Ldir when is_list(Ldir) -> - {ok,filename:join(Ldir|Rest)}; - {error,E} -> {error,E} +lib_file_name(Name) -> + try + App|Path = filename:split(Name), + LibDir = code:lib_dir(list_to_atom(App)), + {ok,filename_join(LibDir|Path)} + catch + _:_ -> error end. -%% read_file(FileName, State) -> {ok,Forms,State} | {error,Error}. +filename_join("." | _|_=Rest) -> + filename_join(Rest); +filename_join(Comp) -> + filename:join(Comp). + +%% lib_read_file(FileName, State) -> +%% {ok,Forms,State} | {error,State} | not_found. +%% Try to read the library file. Try to open the file to make sure +%% that even if we can find the lirbary the file is there. + +lib_read_file(Name, St) -> + case lib_file_name(Name) of
View file
_service:tar_scm:lfe-1.3.tar.gz/src/lfe_macro_record.erl -> _service:tar_scm:lfe-2.1.1.tar.gz/src/lfe_macro_record.erl
Changed
@@ -1,4 +1,4 @@ -%% Copyright (c) 2008-2016 Robert Virding +%% Copyright (c) 2008-2020 Robert Virding %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -12,132 +12,86 @@ %% See the License for the specific language governing permissions and %% limitations under the License. -%% File : lfe_macro_record.erl -%% Author : Robert Virding -%% Purpose : Lisp Flavoured Erlang macro expander for records. +%%% File : lfe_macro_record.erl +%%% Author : Robert Virding +%%% Purpose : Lisp Flavoured Erlang macro expander for records. + +%%% Create macros for defining, creating and accessing records. Note +%%% we still create the older set-Name macros even though they have +%%% been deprecated. -module(lfe_macro_record). -export(define/3,format_error/1). --export(record_set_functions/4). - -import(lists, map/2,foldr/3,concat/1). +-include("lfe.hrl"). -include("lfe_macro.hrl"). %% Errors. -format_error({badrecord,R}) -> - lfe_io:format1("bad definition of record ~w",R); -format_error({undefined_record_field,R,F}) -> - lfe_io:format1("undefined field ~w in record ~w",F,R); -format_error({missing_field_value,R,F}) -> - lfe_io:format1("missing value to field ~w in record ~w",F,R); +format_error({bad_record,Name}) -> + lfe_io:format1(<<"bad definition of record ~w">>,Name); format_error(_) -> "record error". -%% define(Name|FieldDefs, Env, State) -> {Funs,Macs,Env,State}. -%% define(Name, FieldDefs, Env, State) -> {Funs,Macs,Env,State}. +%% define(Name|FieldDefs, Env, State) -> {ok,Form,State}. +%% define(Name, FieldDefs, Env, State) -> {Forms,Env,State}. %% Define a VERY simple record by generating macros for all accesses. %% (define-record point x y) %% => make-point, is-point, match-point, set-point, %% point-x, set-point-x, point-y, set-point-y. define(Name|Fdefs, Env, St0) -> - {Funs,Forms, _,St1} = define(Name, Fdefs, Env, St0), - {yes,progn,'eval-when-compile'|Funs|Forms,St1}. + {Macs,St1} = define(Name, Fdefs, Env, St0), + {yes,progn,'define-record',Name,Fdefs|Macs,St1}; +define(, _Env, _St) -> no. %Undefined macro -define(Name, Fdefs, Env, St) -> +define(Name, Fdefs, _Env, St) when is_atom(Name) -> %% Get field names, default values and indices. Fields = map(fun (F,_,_) when is_atom(F) -> F; (F,_) when is_atom(F) -> F; - (F) when is_atom(F) -> F + (F) when is_atom(F) -> F; + (F) when is_atom(F) -> F; + (_) -> bad_record_error(Name) end, Fdefs), - Defs = map(fun (F,D,_) when is_atom(F) -> ?Q(D); - (F,D) when is_atom(F) -> ?Q(D); - (F) when is_atom(F) -> ?Q(?Q(undefined)) - end, Fdefs), - Findexs = field_indexes(Fields), - %% Make names for helper functions. - Fi = list_to_atom(concat(Name,'-',field,'-',index)), - Fu = list_to_atom(concat(Name,'-',field,'-',update)), - %% Build helper functions. - Funs = index_function(Name, Fi, Findexs), - update_function(Name, Fu, Fi), %% Make access macros. - Macs = make_macro(Name, Defs, Fu), %make-Name - match_macro(Name, Fields, Fu), %match-Name + Macs = make_macro(Name), %make-Name + match_macro(Name), %match-Name test_macro(Name, Fields), %is-Name - set_macro(Name, Fields, Fi), %set-Name - emp_macro(Name, Fields, Fu), %emp-Name + update_macro(Name), %update-Name + set_macro(Name), %set-Name field_macro(Name, Fields), %fields-Name size_macro(Name, Fields) %size-Name | field_macros(Name, Fields), %Name-F,set-Name-F - Type = type_information(Name, Fdefs, St), - %% We can always add type information here as it is stripped later. - Forms = 'extend-module',Type,|Macs, - %% lfe_io:format("~p\n", {Funs,Forms}), - {Funs,Forms,Env,St}. - -field_indexes(Fs) -> field_indexes(Fs, 2). - -field_indexes(F|Fs, N) -> - {F,N}|field_indexes(Fs, N+1); -field_indexes(, _) -> . - -index_function(Name, Fi, Fxs) -> %Get index of field - defun,Fi| - map(fun ({F,I}) -> ?Q(F),I end, Fxs) ++ - f,':',erlang,error, - tuple,?Q(undefined_record_field),?Q(Name),f. - -update_function(Name, Fu, Fi) -> %Update field list - defun,Fu,is,def, - %% Convert default list to tuple to make setting easier. - fletrec,l, - cons,f,cons,v,is,i, - l,is,setelement,'-',Fi,f,1,i,v, - list,f,'_', - ':',erlang,error, - tuple,?Q(missing_field_value),?Q(Name),f, - ,i,i, - 'let',i,l,is,list_to_tuple,def, - tuple_to_list,i. - -make_macro(Name, Defs, Fu) -> + {Macs,St}; +define(Name, _Fdefs, _Env, _St) -> + bad_record_error(Name). + +make_macro(Name) -> Make = list_to_atom(concat('make','-',Name)), - 'defmacro',Make,fds, - 'let',def,list|Defs, - ?BQ(tuple,?Q(Name),?C_A(Fu,fds,def)). + 'defmacro',Make,fds,?BQ('record',Name,?C_A(fds)). -match_macro(Name, Fs, Fu) -> +match_macro(Name) -> Match = list_to_atom(concat('match','-',Name)), - 'defmacro',Match,fds, - 'let',def,list|lists:duplicate(length(Fs),?Q('_')), - ?BQ(tuple,?Q(Name),?C_A(Fu,fds,def)). + 'defmacro',Match,fds,?BQ('record',Name,?C_A(fds)). -test_macro(Name, Fs) -> +test_macro(Name, _Fs) -> Test = list_to_atom(concat('is','-',Name)), - 'defmacro',Test,rec, - ?BQ('is_record',?C(rec),?Q(Name),length(Fs)+1). + 'defmacro',Test,rec,?BQ('is-record',?C(rec),Name). + %% ?BQ('is_record',?C(rec),?Q(Name),length(Fs)+1). -set_macro(Name, Fs, Fi) -> +update_macro(Name) -> + Upd = list_to_atom(concat('update','-',Name)), + defmacro,Upd, + cons,rec,fds, + ?BQ('record-update',?C(rec),Name,?C_A(fds)). + +set_macro(Name) -> Set = list_to_atom(concat('set','-',Name)), defmacro,Set, cons,rec,fds, - 'let',tuple,lets,body, - ':',lfe_macro_record,record_set_functions, - fds,?Q(Name),lambda,f,Fi,f,?Q(rec), - ?BQ('let',rec,?C(rec),?C_A(lets), - 'if',is_record,rec,?Q(Name),length(Fs)+1, - ?C(body), - error,{badrecord,Name}). - -emp_macro(Name, Fs, Fu) -> - EMP = list_to_atom(concat('emp','-',Name)), - 'defmacro',EMP,fds, - 'let',def,list|lists:duplicate(length(Fs),?Q(?Q('_'))), - ?BQ(tuple,?Q(Name),?C_A(Fu,fds,def)). + ?BQ('record-update',?C(rec),Name,?C_A(fds)). field_macro(Name, Fs) -> Recfields = list_to_atom(concat('fields','-',Name)), @@ -145,51 +99,23 @@ size_macro(Name, Fs) -> Recsize = list_to_atom(concat('size','-',Name)), - 'defmacro',Recsize,,length(Fs). + 'defmacro',Recsize,,length(Fs)+1. %Don't forget the record name field_macros(Name, Fs) -> - Fis = field_indexes(Fs), %Calculate indexes - foldr(fun ({F,N}, Fas) -> + Fun = fun (F, Fas) -> Get = list_to_atom(concat(Name,'-',F)), Set = list_to_atom(concat('set-',Name,'-',F)), + Upd = list_to_atom(concat('update-',Name,'-',F)), defmacro,Get, - ,N, %Field index - list,rec, %Field value - ?BQ(test_and_do(Name, Fs, rec, , element,N, rec)), - %%list,rec,?BQ(element,N,?C(rec)),
View file
_service:tar_scm:lfe-2.1.1.tar.gz/src/lfe_macro_struct.erl
Added
@@ -0,0 +1,46 @@ +%% Copyright (c) 2008-2020 Robert Virding +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. + +%%% File : lfe_macro_struct.erl +%%% Author : Robert Virding +%%% Purpose : Lisp Flavoured Erlang macro expander for structs. + +-module(lfe_macro_struct). + +-export(define/3,format_error/1). + +-import(lists, map/2,foldr/3,concat/1). + +-include("lfe.hrl"). +-include("lfe_macro.hrl"). + +%% Errors. +format_error(bad_struct_def) -> <<"bad definition of struct">>; +format_error(_) -> "struct error". + +define(Fdefs0, Env, St0) -> + Fdefs1 = evaluate_fdefs(Fdefs0, Env), + {yes,progn,'define-struct',Fdefs1,St0}. + +evaluate_fdefs(Fdefs0, Env) -> + Fun = fun (F,Def,T) when is_atom(F) -> F,lfe_eval:expr(Def, Env),T; + (F,Def) when is_atom(F) -> F,lfe_eval:expr(Def, Env); + (F) when is_atom(F) -> F; + (F) when is_atom(F) -> F; + (_) -> bad_struct_def_error() + end, + Fdefs1 = lists:map(Fun, Fdefs0), + Fdefs1. + +bad_struct_def_error() -> error(bad_struct_def).
View file
_service:tar_scm:lfe-1.3.tar.gz/src/lfe_ms.erl -> _service:tar_scm:lfe-2.1.1.tar.gz/src/lfe_ms.erl
Changed
@@ -1,4 +1,4 @@ -%% Copyright (c) 2008-2013 Robert Virding +%% Copyright (c) 2008-2020 Robert Virding %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -27,28 +27,32 @@ -module(lfe_ms). --export(expand/1,format_error/1). +-export(expand/1,expand/2,format_error/1). -import(lists, foldr/3,mapfoldl/3). +-include("lfe.hrl"). + %% ets:test_ms/2. %% format_error(Error) -> ErrorString. format_error(match_spec_head) -> "Illegal number of head arguments". --define(Q(E), quote,E). %We do a lot of quoting! - -record(ms, {dc=1, %Dollar variable count from 1 bs=, %Variable/$var bindings + dialect=ets, %Which dialect are we doing where=guard %Where in spec head/guard/body }). %% expand(MSBody) -> Expansion. +%% expand(Dialect, MSBody) -> Expansion. %% Expand the match spec body. -expand(Cls) -> - case catch clauses(Cls, #ms{}) of +expand(Cls) -> expand(table, Cls). + +expand(Dialect, Cls) when Dialect =:= table ; Dialect =:= trace -> + case catch clauses(Cls, #ms{dialect=Dialect}) of {error,E} -> error(E); %Signals errors {'EXIT',E} -> error(E); %Signals errors {Exp,_} -> Exp %Hurrah it worked @@ -85,19 +89,42 @@ case Pats of %Test for top-level aliasing '=',S,Pat when is_atom(S) -> St2 = new_binding(S, '$_', St1), - pattern(Pat, St2); + head_pattern(Pat, St2); '=',Pat,S when is_atom(S) -> St2 = new_binding(S, '$_', St1), - pattern(Pat, St2); - Pat -> pattern(Pat, St1); - _ -> throw({error,match_spec_head}) %Wrong size + head_pattern(Pat, St2); + Pat -> head_pattern(Pat, St1); + _ -> throw({error,{match_spec_head,Pats}}) %Wrong size end. +%% head_pattern(Pattern, State) -> {Pattern,State}. +%% Check the head pattern has the right format for the dialect. + +head_pattern(Pat, St) -> %Just a variable + check_head(Pat, St#ms.dialect), %Correct format + pattern(Pat, St). + +check_head(Pat, _) when is_atom(Pat) -> ok; %Variable +check_head(Pat, table) when is_tuple(Pat) -> ok; +check_head(?Q(Pat), table) when is_tuple(Pat) -> ok; +check_head(tuple|_, table) -> ok; +check_head('record'|_, table) -> ok; +%% make-record has been deprecated but we sill accept it for now. +check_head('make-record'|_, table) -> ok; +check_head(?Q(Pat), trace) when is_list(Pat) -> ok; +check_head(list|_, trace) -> ok; +check_head(cons|_, trace) -> ok; +check_head(, trace) -> ok; +check_head(Pat, _Type) -> + throw({error,{match_spec_head,Pat}}). + +%% pattern(Pattern, State) -> {Pattern,State}. + pattern('_', St) -> {?Q('_'),St}; pattern(Symb, St0) when is_atom(Symb) -> %Variable {Dv,St1} = pat_binding(Symb, St0), {?Q(Dv),St1}; -pattern(quote,_=E, St) -> {E,St}; +pattern(?Q(_)=E, St) -> {E,St}; pattern(cons,H0,T0, St0) -> {H1,St1} = pattern(H0, St0), {T1,St2} = pattern(T0, St1), @@ -108,6 +135,21 @@ pattern(tuple|Ps0, St0) -> {Ps1,St1} = pat_list(Ps0, St0), {tuple|Ps1,St1}; +pattern('=',L0,R0, St0) -> %General aliasing + {L1,St1} = pattern(L0, St0), + {R1,St2} = pattern(R0, St1), + {'=',L1,R1,St2}; +pattern('record',R|Fs0, St0) -> + %% This is in a term but is going to be used as a pattern! + {Fs1,St1} = pat_rec_fields(Fs0, St0), + {'record',R|Fs1,St1}; +%% make-record has been deprecated but we sill accept it for now. +pattern('make-record',R|Fs0, St0) -> + %% This is in a term but is going to be used as a pattern! + {Fs1,St1} = pat_rec_fields(Fs0, St0), + {'make-record',R|Fs1,St1}; +pattern('record-index',R,F, St) -> + {'record-index',R,F,St}; %% Support old no constructor style list forms. pattern(H0|T0, St0) -> {H1,St1} = pattern(H0, St0), @@ -117,6 +159,20 @@ pat_list(Ps, St) -> mapfoldl(fun pattern/2, St, Ps). +%% pat_rec_fields(Fields, State) -> {Patterns,State}. + +pat_rec_fields(F,P0|Fs0, St0) when is_atom(F) -> + %% Field names go straight through untouched. + {P1,St1} = pattern(P0, St0), + {Fs1,St2} = pat_rec_fields(Fs0, St1), + {F,P1|Fs1,St2}; +pat_rec_fields(F0,P0|Fs0, St0) -> + {F1,St1} = pattern(F0, St0), + {P1,St2} = pattern(P0, St1), + {Fs1,St3} = pat_rec_fields(Fs0, St2), + {F1,P1|Fs1,St3}; +pat_rec_fields(, St) -> {,St}. + %% pat_binding(Var, Status) -> {DVar,Status}. %% Get dollar var for variable, creating a new one if neccessary. @@ -156,14 +212,14 @@ {ok,Dv} -> {?Q(Dv),St}; %Head variable error -> {S,St} %Free variable, need binding end; -expr(quote,A=E, St) when is_atom(A) -> %Atom +expr(?Q(A)=E, St) when is_atom(A) -> %Atom case atom_to_list(A) of $$|_ -> {tuple,?Q(const),E,St}; %Catch dollar variables _ -> {E,St} end; -expr(quote,T, St) when is_tuple(T) -> %Must tuple tuples +expr(?Q(T), St) when is_tuple(T) -> %Must tuple tuples {tuple,T,St}; -expr(quote,_=E, St) -> {E,St}; %No need for {const,E}? +expr(?Q(_)=E, St) -> {E,St}; %No need for {const,E}? expr(cons,H0,T0, St0) -> {H1,St1} = expr(H0, St0), {T1,St2} = expr(T0, St1), @@ -177,25 +233,56 @@ expr(binary|Segs0, St0) -> {Segs1,St1} = expr_bitsegs(Segs0, St0), {binary|Segs1,St1}; +%% Record special forms. +expr('record',Name|Fs, St0) -> + %% This is in a term and is going to be used as an expression! + {Efs,St1} = expr_rec_fields(Fs, St0), + {tuple,'record',Name|Efs,St1}; %Must tuple tuples +%% make-record has been deprecated but we sill accept it for now. +expr('make-record',Name|Fs, St0) -> + %% This is in a term and is going to be used as an expression! + {Efs,St1} = expr_rec_fields(Fs, St0), + {tuple,'make-record',Name|Efs,St1}; %Must tuple tuples +expr('is-record',E,Name, St0) -> + {Ee,St1} = expr(E, St0), + %% io:format(user, "is-record ~p ~p\n", E,Name), + {tuple,?Q('is_record'),Ee,?Q(Name),St1}; + %% {tuple,'is-record',Ee,Name,St1}; +expr('record-index',Name,F, St) -> + {'record-index',Name,F,St}; +expr('record-field',E,Name,F, St0) -> + %% We must remove all checks and return simple call to element/2. + {Ee,St1} = expr(E, St0), + {tuple,?Q(element),'record-index',Name,F,Ee,St1}; + %% {tuple,'record-field',Ee,Name,F,St1}; +expr('record-update',E,Name|Fs, St0) -> + %% We must remove all checks and return simple nested setelement/3 calls. + {Ee,St1} = expr(E, St0), + {Efs,St2} = expr_rec_fields(Fs, St1), + Set = expr_set_record(Efs, Ee, Name), + {Set,St2}; + %% {tuple,'record-update',Ee,Name|Efs,St2}; %% Special match spec calls. expr(bindings, St) -> {?Q('$*'),St}; %Special calls expr(object, St) -> {?Q('$_'),St}; %% General function calls. expr(call,?Q(erlang),?Q(Op)|Es0, St0) when is_atom(Op) -> Ar = length(Es0), - case is_ms_erlang_func(Op, Ar) of + case is_ms_erlang_func(Op, Ar, St0#ms.where) of true -> {Es1,St1} = expr_list(Es0, St0), {tuple,?Q(Op)|Es1,St1}; - false -> throw({error,{illegal_ms_func,{erlang,Op,Ar}}}) + false -> illegal_func_error({erlang,Op,Ar}) end;
View file
_service:tar_scm:lfe-1.3.tar.gz/src/lfe_parse.erl -> _service:tar_scm:lfe-2.1.1.tar.gz/src/lfe_parse.erl
Changed
@@ -1,4 +1,4 @@ -%% Copyright (c) 2009-2017 Robert Virding +%% Copyright (c) 2009-2020 Robert Virding %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License.
View file
_service:tar_scm:lfe-1.3.tar.gz/src/lfe_parse.spell1 -> _service:tar_scm:lfe-2.1.1.tar.gz/src/lfe_parse.spell1
Changed
@@ -1,5 +1,5 @@ %% -*- mode: erlang -*- -%% Copyright (c) 2008-2015 Robert Virding +%% Copyright (c) 2008-2020 Robert Virding %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License.
View file
_service:tar_scm:lfe-1.3.tar.gz/src/lfe_qlc.erl -> _service:tar_scm:lfe-2.1.1.tar.gz/src/lfe_qlc.erl
Changed
@@ -1,4 +1,4 @@ -%% Copyright (c) 2008-2016 Robert Virding +%% Copyright (c) 2008-2020 Robert Virding %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License.
View file
_service:tar_scm:lfe-1.3.tar.gz/src/lfe_scan.xrl -> _service:tar_scm:lfe-2.1.1.tar.gz/src/lfe_scan.xrl
Changed
@@ -1,4 +1,4 @@ -%% Copyright (c) 2008-2013 Robert Virding +%% Copyright (c) 2008-2020 Robert Virding %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -64,7 +64,7 @@ #{D}*xX{SYM}+ : base_token(skip_past(TokenChars, $x, $X), 16, TokenLine). #{D}*rR{SYM}+ : %% Scan over digit chars to get base. - {Base,_|Ds} = base1(tl(TokenChars), 10, 0), + {Base,_|Ds} = base_collect(tl(TokenChars), 10, 0), base_token(Ds, Base, TokenLine). %% String @@ -88,7 +88,7 @@ %% Strip sharpsign single-quote. FunStr = string:substr(TokenChars,3), {token,{'#\'',TokenLine,FunStr}}. -%% Atoms +%% Numbers +-?{D}+ : case catch {ok,list_to_integer(TokenChars)} of {ok,I} -> {token,{number,TokenLine,I}}; @@ -99,12 +99,18 @@ {ok,F} -> {token,{number,TokenLine,F}}; _ -> {error,"illegal float"} end. +%% Elixir alias symbol +#eE{SSYM}{SYM}* : + %% Strip sharpsign e | E. + AliasStr = string:substr(TokenChars,3), + symbol_token("Elixir." ++ AliasStr, TokenLine). +%% Symbols {SSYM}{SYM}* : symbol_token(TokenChars, TokenLine). {WS}+ : skip_token. Erlang code. -%% Copyright (c) 2008-2013 Robert Virding +%% Copyright (c) 2008-2020 Robert Virding %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -167,22 +173,25 @@ base_token(Cs, B, L) -> base_token(Cs, B, +1, L). base_token(Cs, B, S, L) -> - case base1(Cs, B, 0) of + case base_collect(Cs, B, 0) of {N,} -> {token,{number,L,S*N}}; {_,_} -> {error,"illegal based number"} end. -base1(C|Cs, Base, SoFar) when C >= $0, C =< $9, C < Base + $0 -> +%% base_collect(Chars, Base, SoFar) -> {Number,RestChars}. +%% Collect all numeric characters of base Base. + +base_collect(C|Cs, Base, SoFar) when C >= $0, C =< $9, C < Base + $0 -> Next = SoFar * Base + (C - $0), - base1(Cs, Base, Next); -base1(C|Cs, Base, SoFar) when C >= $a, C =< $z, C < Base + $a - 10 -> + base_collect(Cs, Base, Next); +base_collect(C|Cs, Base, SoFar) when C >= $a, C =< $z, C < Base + $a - 10 -> Next = SoFar * Base + (C - $a + 10), - base1(Cs, Base, Next); -base1(C|Cs, Base, SoFar) when C >= $A, C =< $Z, C < Base + $A - 10 -> + base_collect(Cs, Base, Next); +base_collect(C|Cs, Base, SoFar) when C >= $A, C =< $Z, C < Base + $A - 10 -> Next = SoFar * Base + (C - $A + 10), - base1(Cs, Base, Next); -base1(C|Cs, _Base, SoFar) -> {SoFar,C|Cs}; -base1(, _Base, N) -> {N,}. + base_collect(Cs, Base, Next); +base_collect(C|Cs, _Base, SoFar) -> {SoFar,C|Cs}; +base_collect(, _Base, N) -> {N,}. -define(IS_UNICODE(C), ((C >= 0) and (C =< 16#10FFFF))). @@ -192,7 +201,7 @@ %% unicode range. char_token($x,C|Cs, L) -> - case base1(C|Cs, 16, 0) of + case base_collect(C|Cs, 16, 0) of {N,} when ?IS_UNICODE(N) -> {token,{number,L,N}}; _ -> {error,"illegal character"} end; @@ -203,9 +212,9 @@ %% We know that the input string is correct. chars($\\,$x,C|Cs0) -> - case hex_char(C) of + case is_hex_char(C) of true -> - case base1(C|Cs0, 16, 0) of + case base_collect(C|Cs0, 16, 0) of {N,$;|Cs1} -> N|chars(Cs1); _Other -> escape_char($x)|chars(C|Cs0) end; @@ -215,10 +224,10 @@ chars(C|Cs) -> C|chars(Cs); chars() -> . -hex_char(C) when C >= $0, C =< $9 -> true; -hex_char(C) when C >= $a, C =< $f -> true; -hex_char(C) when C >= $A, C =< $F -> true; -hex_char(_) -> false. +is_hex_char(C) when C >= $0, C =< $9 -> true; +is_hex_char(C) when C >= $a, C =< $f -> true; +is_hex_char(C) when C >= $A, C =< $F -> true; +is_hex_char(_) -> false. escape_char($b) -> $\b; %\b = BS escape_char($t) -> $\t; %\t = TAB @@ -229,7 +238,7 @@ escape_char($e) -> $\e; %\e = ESC escape_char($s) -> $\s; %\s = SPC escape_char($d) -> $\d; %\d = DEL -escape_char(C) -> C. +escape_char(C) -> C. %\Other = Other %% Block Comment: %% Provide a sensible error when people attempt to include nested @@ -245,12 +254,15 @@ end. %% skip_until(String, Char1, Char2) -> String. -%% skip_past(String, Char1, Char2) -> String. +%% Skip characters until we get a C1 or C2. %% skip_until(C|_=Cs, C1, C2) when C =:= C1 ; C =:= C2 -> Cs; %% skip_until(_|Cs, C1, C2) -> skip_until(Cs, C1, C2); %% skip_until(, _, _) -> . +%% skip_past(String, Char1, Char2) -> String. +%% Skip characters until we get a C1 or C2 and then skip past it. + skip_past(C|Cs, C1, C2) when C =:= C1 ; C =:= C2 -> Cs; skip_past(_|Cs, C1, C2) -> skip_past(Cs, C1, C2); skip_past(, _, _) -> .
View file
_service:tar_scm:lfe-1.3.tar.gz/src/lfe_shell.erl -> _service:tar_scm:lfe-2.1.1.tar.gz/src/lfe_shell.erl
Changed
@@ -1,4 +1,4 @@ -%% Copyright (c) 2008-2016 Robert Virding +%% Copyright (c) 2008-2022 Robert Virding %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -27,30 +27,27 @@ -module(lfe_shell). -export(start/0,start/1,server/0,server/1, - run_script/2,run_script/3,run_string/2,run_string/3). + run_script/2,run_script/3, + run_strings/1,run_strings/2,run_string/1,run_string/2, + new_state/2,new_state/3,upd_state/3). %% The shell commands which generally callable. --export(c/1,c/2,cd/1,doc/1,docs/1,ec/1,ec/2,ep/1,ep/2,epp/1,epp/2,help/0, - i/0,i/1,l/1,ls/1,clear/0,m/0,m/1,pid/3,p/1,p/2,pp/1,pp/2,pwd/0, - q/0,flush/0,regs/0,exit/0). - --import(lfe_env, new/0,add_env/2, - add_vbinding/3,add_vbindings/2,is_vbound/2,get_vbinding/2, - fetch_vbinding/2,del_vbinding/2, - add_fbinding/4,add_fbindings/2,get_fbinding/3,add_ibinding/5, - get_gbinding/3,add_mbinding/3). +-export(c/1,c/2,cd/1,ec/1,ec/2,ep/1,ep/2,epp/1,epp/2,help/0,h/1,h/2,h/3, + i/0,i/1,i/3,l/1,ls/1,clear/0,m/0,m/1,pid/3,p/1,p/2,pp/1,pp/2,pwd/0, + q/0,flush/0,regs/0,exit/0). -import(orddict, store/3,find/2). --import(ordsets, add_element/2). -import(lists, reverse/1,foreach/2). -include("lfe.hrl"). +-include("lfe_docs.hrl"). -%% Colours for the LFE banner +%% Coloured strings for the LFE banner, red, green, yellow and blue. -define(RED(Str), "\e31m" ++ Str ++ "\e0m"). -define(GRN(Str), "\e1;32m" ++ Str ++ "\e0m"). -define(YLW(Str), "\e1;33m" ++ Str ++ "\e0m"). -define(BLU(Str), "\e1;34m" ++ Str ++ "\e0m"). +-define(BOLD(Str), "\e1m" ++ Str ++ "\e0m"). %% -compile(export_all). @@ -65,41 +62,68 @@ -record(state, {curr,save,base, %Current, save and base env slurp=false}). %Are we slurped? +%% run_script(File, Args) -> {Value,State}. +%% run_string(File, Args, State) -> {Value,State}. + +-spec run_script(_, _) -> no_return(). +-spec run_script(_, _, _) -> no_return(). + run_script(File, Args) -> - run_script(File, Args, lfe_env:new()). + run_script(File, Args, new_state(File, Args)). + +run_script(File, Args, St0) -> + St1 = upd_state(File, Args, St0), + run_file(File, St1). + +%% run_strings(Strings) -> {Value,State}. +%% run_strings(Strings, State) -> {Value,State}. + +run_strings(Strings) -> + run_strings(Strings, new_state("lfe", )). + +run_strings(Strings, St) -> + lists:foldl(fun (S, St0) -> + {_,St1} = run_string(S, St0), + St1 + end, St, Strings). -run_script(File, Args, Env) -> - St = new_state(File, Args, Env), - run(File, St). +%% run_string(String) -> {Value,State}. +%% run_string(String, State) -> {Value,State}. -run_string(String, Args) -> - run_string(String, Args, lfe_env:new()). +run_string(String) -> + run_string(String, new_state("lfe", )). -run_string(String, As, Env) -> - St = new_state("lfe", As, Env), +run_string(String, St0) -> + St1 = upd_state(String, , St0), case read_script_string(String) of {ok,Forms} -> - run_loop(Forms, , St); + run_loop(Forms, St1); {error,E} -> slurp_errors("lfe", E), - {error,St} + {error,St1} end. -start() -> start(default). +%% start() -> Pid. +%% start(State) -> Pid. -start(Env) -> - spawn(fun () -> server(Env) end). +start() -> + spawn(fun () -> server() end). -server() -> server(default). +start(St) -> + spawn(fun () -> server(St) end). -server(default) -> - server(lfe_env:new()); -server(Env) -> - process_flag(trap_exit, true), %Must trap exists - io:put_chars(make_banner()), +%% server() -> no_return(). +%% server(State) -> no_return(). + +server() -> %% Create a default base env of predefined shell variables with %% default nil bindings and basic shell macros. - St = new_state("lfe", , Env), + St = new_state("lfe", ), + server(St). + +server(St) -> + process_flag(trap_exit, true), %Must trap exists + display_banner(), %% Set shell io to use LFE expand in edlin, ignore error. io:setopts({expand_fun,fun (B) -> lfe_edlin_expand:expand(B) end}), Eval = start_eval(St), %Start an evaluator @@ -186,7 +210,7 @@ end, Ff = fun (T, I) -> lfe_io:prettyprint1(T, 15, I, 80) end, Cs = lfe_lib:format_exception(Class, Reason, Stk, Sf, Ff, 1), - io:put_chars(Cs), + io:put_chars("** " ++ Cs), %Make it more note worthy io:nl(). %% read_expression(Prompt, Evaluator, State) -> {Return,Evaluator}. @@ -225,11 +249,23 @@ ?GRN(" |`-.._") ++ ?YLW("/") ++ ?GRN("_") ++ ?YLW("\\\\") ++ ?GRN("_.-':") ++ " | Type " ++ ?GRN("(help)") ++ " for usage info.\n" ++ ?GRN(" | ") ++ ?RED("g") ++ ?GRN(" |_ \\") ++ " |\n" ++ ?GRN(" | ") ++ ?RED("n") ++ ?GRN(" | |") ++ " | Docs: " ++ ?BLU("http://docs.lfe.io/") ++ "\n" ++ - ?GRN(" | ") ++ ?RED("a") ++ ?GRN(" / /") ++ " | Source: " ++ ?BLU("http://github.com/rvirding/lfe") ++ "\n" ++ + ?GRN(" | ") ++ ?RED("a") ++ ?GRN(" / /") ++ " | Source: " ++ ?BLU("http://github.com/lfe/lfe") ++ "\n" ++ ?GRN(" \\ ") ++ ?RED("l") ++ ?GRN(" |_/") ++ " |\n" ++ ?GRN(" \\ ") ++ ?RED("r") ++ ?GRN(" /") ++ " | LFE v~s ~s\n" ++ ?GRN(" `-") ++ ?RED("E") ++ ?GRN("___.-'") ++ "\n\n", get_lfe_version(), get_abort_message()). +display_banner() -> + %% When LFE is called with -noshell, we want to skip the banner. Also, there may be + %% circumstances where the shell is desired, but the banner needs to be disabled, + %% thus we want to support both use cases. + case init:get_argument(noshell) of + error -> case init:get_argument(nobanner) of + error -> io:put_chars(make_banner()); + _ -> false + end; + _ -> false + end. + get_abort_message() -> %% We can update this later to check for env variable settings for %% shells that require a different control character to abort, such @@ -244,35 +280,44 @@ %% Generate a new shell state with all the default functions, macros %% and variables. -%% new_state(Script, Args) -> new_state(Script, Args, lfe_env:new()). +new_state(Script, Args) -> + new_state(Script, Args, lfe_env:new()). new_state(Script, Args, Env0) -> - Env1 = add_vbinding('script-name', Script, Env0), - Env2 = add_vbinding('script-args', Args, Env1), + Env1 = lfe_env:add_vbinding('script-name', Script, Env0), + Env2 = lfe_env:add_vbinding('script-args', Args, Env1), Base0 = add_shell_functions(Env2), Base1 = add_shell_macros(Base0), Base2 = add_shell_vars(Base1), #state{curr=Base2,save=Base2,base=Base2,slurp=false}. +upd_state(Script, Args, #state{curr=Curr,save=Save,base=Base}=St) -> + %% Update an environment with with script name and args. + Upd = fun (E0) -> + E1 = lfe_env:add_vbinding('script-name', Script, E0), + lfe_env:add_vbinding('script-args', Args, E1) + end, + St#state{curr=Upd(Curr),save=Upd(Save),base=Upd(Base)}. + add_shell_vars(Env0) -> %% Add default shell expression variables. - Env1 = foldl(fun (Symb, E) -> add_vbinding(Symb, , E) end, Env0, + Env1 = foldl(fun (Symb, E) -> lfe_env:add_vbinding(Symb, , E) end, Env0, '+','++','+++','-','*','**','***'),
View file
_service:tar_scm:lfe-2.1.1.tar.gz/src/lfe_shell_docs.erl
Added
@@ -0,0 +1,91 @@ +%% Copyright (c) 2022 Robert Virding +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. + +%% File : lfe_shell_docs.erl +%% Author : Robert Virding +%% Purpose : Render LFE docs for output in shell. + +%% The interface is loosely modelled on the shell_docs module. + +-module(lfe_shell_docs). + +-export(render/2,render/3,render/4). + +-include("lfe.hrl"). +-include("lfe_docs.hrl"). + +%% Coloured strings for the LFE banner, red, green, yellow and blue. +-define(RED(Str), "\e31m" ++ Str ++ "\e0m"). +-define(GRN(Str), "\e1;32m" ++ Str ++ "\e0m"). +-define(YLW(Str), "\e1;33m" ++ Str ++ "\e0m"). +-define(BLU(Str), "\e1;34m" ++ Str ++ "\e0m"). +-define(BOLD(Str), "\e1m" ++ Str ++ "\e0m"). + +%% render(Module, Docs) -> unicode:chardata(). + +render(Bin, Docs) when is_binary(Bin) -> + {ok,{Mod,_}} = beam_lib:chunks(Bin, , ), %Sneaky! + render(Mod, Docs); +render(Mod, #docs_v1{format = ?LFE_FORMAT, module_doc=Mdoc}) -> + red_line(60), + lfe_io:format1(?BLU("~p")++"\n\n", Mod), + return_doc(Mod, Mdoc). + +%% render(Module, Function, Docs) -> unicode:chardata(). + +render(_Mod, Name, #docs_v1{format = ?LFE_FORMAT, docs = Docs}) -> + Render = fun ({{function,_Func,_Ar},_,Sig,Doc,Meta}) -> + red_line(60), + return_sig(function, Sig, Meta), + return_doc(Sig, Doc); + ({{macro,_Macro,_},_,Sig,Doc,Meta}) -> + red_line(60), + return_sig(macro, Sig, Meta), + return_doc(Sig, Doc) + end, + Ret = Render(F) || {{_,N,_},_,_,_,_}=F <- Docs, N =:= Name , + return_render(Ret, function_missing). + +%% render(Module, Function, Arity, Docs) -> unicode:chardata(). + +render(_Mod, Name, Arity, #docs_v1{format = ?LFE_FORMAT, docs = Docs}) -> + Render = fun ({{function,_Func,_Ar},_,Sig,Doc,Meta}) -> + red_line(60), + return_sig(function, Sig, Meta), + return_doc(Sig, Doc) + end, + Ret = Render(F) || {{function,N,A},_,_,_,_}=F <- Docs, + N =:= Name, A =:= Arity , + return_render(Ret, function_missing). + +return_doc(_Missing, #{<<"en">> := Dv}) -> + lfe_io:format1("~s\n", Dv); +return_doc(Missing, None) when None =:= none; None =:= #{} -> + lfe_io:format1(<<"No documentation for ~s\n">>, Missing); +return_doc(Missing, _Docs) -> + lfe_io:format1(<<"Unknown format for ~s\n">>, Missing). + +%% return_sig(_Type, _Sig, #{signature:=Spec}) -> +%% lfe_io:format1(?BLU("~s") ++ "\n", erl_pp:form(Spec)); +return_sig(Type, Sig, _Meta) -> + lfe_io:format1(?BLU("~s ~s") ++ "\n\n", Type,Sig). + +return_render(, Error) -> {error,Error}; +return_render(FDocs, _Error) -> FDocs. + +%% red_line(Length) -> ok. +%% Output a red line of Length characters. + +red_line(Len) -> + io_lib:format(?RED("~*c")++"\n", Len,$-).
View file
_service:tar_scm:lfe-2.1.1.tar.gz/src/lfe_struct.erl
Added
@@ -0,0 +1,29 @@ +%% Copyright (c) 2022 Robert Virding +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. + +%% File : lfe_struct.erl +%% Author : Robert Virding +%% Purpose : Lisp Flavoured Erlang library for elixir structs. + +-module(lfe_struct). + +-export(to_assocs/1). + +-include("lfe.hrl"). + +to_assocs(Key,Val|Kvs) -> + tuple,Key,Val|to_assocs(Kvs); +to_assocs(Key) -> %Should we catch this? + error({missing_struct_field_value,Key}); +to_assocs() -> .
View file
_service:tar_scm:lfe-2.1.1.tar.gz/src/lfe_translate.erl
Added
@@ -0,0 +1,1698 @@ +%% Copyright (c) 2008-2021 Robert Virding +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. + +%% File : lfe_trans.erl +%% Author : Robert Virding +%% Purpose : Lisp Flavoured Erlang translator. + +%%% Translate LFE code to/from vanilla Erlang AST. +%%% +%%% Note that we don't really check code here as such, we assume the +%%% input is correct. If there is an error in the input we just fail. +%%% This allows us to accept forms which are actually illegal but we +%%% may special case, for example functions call in patterns which +%%% will become macro expansions. +%%% +%%% Having import from and rename forces us to explicitly convert the +%%% call as we can't use an import attribute to do this properly for +%%% us. Hence we collect the imports in lfe_codegen and pass them onto +%%% us. +%%% +%%% Module aliases are collected in lfe_codegen and passed on to us. + +-module(lfe_translate). + +-export(from_expr/1,from_expr/2,from_body/1,from_body/2,from_lit/1). + +-export(to_expr/2,to_expr/3,to_exprs/2,to_exprs/3). +-export(to_gexpr/2,to_gexpr/3,to_gexprs/2,to_gexprs/3,to_lit/2). + +-include("lfe.hrl"). + +-record(from, {vc=0 %Variable counter + }). + +%% from_expr(AST) -> Sexpr. +%% from_expr(AST, Variables) -> {Sexpr,Variables}. +%% from_body(AST) -> Sexpr. +%% from_body(AST, Variables) -> {Sexpr,Variables}. +%% Translate a vanilla Erlang expression into LFE. The main +%% difficulty is in the handling of variables. The implicit matching +%% of known variables in vanilla must be translated into explicit +%% equality tests in guards (which is what the compiler does +%% internally). For this we need to keep track of visible variables +%% and detect when they reused in patterns. + +from_expr(E) -> + {S,_,_} = from_expr(E, ordsets:new(), #from{}), + S. + +from_expr(E, Vs0) -> + Vt0 = ordsets:from_list(Vs0), %We are clean + {S,Vt1,_} = from_expr(E, Vt0, #from{}), + {S,ordsets:to_list(Vt1)}. + +from_body(Es) -> + {Les,_,_} = from_body(Es, ordsets:new(), #from{}), + progn|Les. + +from_body(Es, Vs0) -> + Vt0 = ordsets:from_list(Vs0), %We are clean + {Les,Vt1,_} = from_body(Es, Vt0, #from{}), + {progn|Les,ordsets:to_list(Vt1)}. + +%% from_expr(AST, VarTable, State) -> {Sexpr,VarTable,State}. +%% Convert one expression from Erlang AST to an LFE form. + +from_expr({var,_,V}, Vt, St) -> {V,Vt,St}; %Unquoted atom +from_expr({nil,_}, Vt, St) -> {,Vt,St}; +from_expr({integer,_,I}, Vt, St) -> {I,Vt,St}; +from_expr({float,_,F}, Vt, St) -> {F,Vt,St}; +from_expr({atom,_,A}, Vt, St) -> {?Q(A),Vt,St}; %Quoted atom +from_expr({string,_,S}, Vt, St) -> {?Q(S),Vt,St}; %Quoted string +from_expr({cons,_,H,T}, Vt0, St0) -> + {Car,Vt1,St1} = from_expr(H, Vt0, St0), + {Cdr,Vt2,St2} = from_expr(T, Vt1, St1), + {from_cons(Car, Cdr),Vt2,St2}; +%% {cons,Car,Cdr,Vt2,St2}; +from_expr({tuple,_,Es}, Vt0, St0) -> + {Ss,Vt1,St1} = from_expr_list(Es, Vt0, St0), + {tuple|Ss,Vt1,St1}; +from_expr({bin,_,Segs}, Vt0, St0) -> + {Ss,Vt1,St1} = from_bitsegs(Segs, Vt0, St0), + {binary|Ss,Vt1,St1}; +from_expr({map,_,Assocs}, Vt0, St0) -> %Build a map + {Ps,Vt1,St1} = from_map_assocs(Assocs, Vt0, St0), + {map|Ps,Vt1,St1}; +from_expr({map,_,Map,Assocs}, Vt0, St0) -> %Update a map + {Lm,Vt1,St1} = from_expr(Map, Vt0, St0), + from_map_update(Assocs, nul, Lm, Vt1, St1); +%% Record special forms, though some are function calls in Erlang. +from_expr({record,_,Name,Fs}, Vt0, St0) -> + {Lfs,Vt1,St1} = from_record_fields(Fs, Vt0, St0), + {'record',Name|Lfs,Vt1,St1}; +from_expr({call,_,{atom,_,is_record},E,{atom,_,Name}}, Vt0, St0) -> + {Le,Vt1,St1} = from_expr(E, Vt0, St0), + {'is-record',Le,Name,Vt1,St1}; +from_expr({record_index,_,Name,{atom,_,F}}, Vt, St) -> %We KNOW! + {'record-index',Name,F,Vt,St}; +from_expr({record_field,_,E,Name,{atom,_,F}}, Vt0, St0) -> %We KNOW! + {Le,Vt1,St1} = from_expr(E, Vt0, St0), + {'record-field',Le,Name,F,Vt1,St1}; +from_expr({record,_,E,Name,Fs}, Vt0, St0) -> + {Le,Vt1,St1} = from_expr(E, Vt0, St0), + {Lfs,Vt2,St2} = from_record_fields(Fs, Vt1, St1), + {'record-update',Le,Name|Lfs,Vt2,St2}; +from_expr({record_field,_,_,_}=M, Vt, St) -> %Pre R16 packages + from_package_module(M, Vt, St); +%% Function special forms. +from_expr({'fun',_,{clauses,Cls}}, Vt, St0) -> + {Lcls,St1} = from_fun_cls(Cls, Vt, St0), + {'match-lambda'|Lcls,Vt,St1}; %Don't bother using lambda +from_expr({'fun',_,{function,F,A}}, Vt, St) -> + %% These are just literal values. + {function,F,A,Vt,St}; +from_expr({'fun',_,{function,M,F,A}}, Vt, St) -> + %% These are abstract values. + {function,from_lit(M),from_lit(F),from_lit(A),Vt,St}; +%% Core control special forms. +from_expr({match,_,_,_}=Match, Vt, St) -> + from_match(Match, Vt, St); +from_expr({block,_,Es}, Vt, St) -> + from_block(Es, Vt, St); +from_expr({'if',_,Cls}, Vt0, St0) -> %This is the Erlang if + {Lcls,Vt1,St1} = from_icrt_cls(Cls, Vt0, St0), + {'case',|Lcls,Vt1,St1}; +from_expr({'case',_,E,Cls}, Vt0, St0) -> + {Le,Vt1,St1} = from_expr(E, Vt0, St0), + {Lcls,Vt2,St2} = from_icrt_cls(Cls, Vt1, St1), + {'case',Le|Lcls,Vt2,St2}; +from_expr({'receive',_,Cls}, Vt0, St0) -> + {Lcls,Vt1,St1} = from_icrt_cls(Cls, Vt0, St0), + {'receive'|Lcls,Vt1,St1}; +from_expr({'receive',_,Cls,Timeout,Body}, Vt0, St0) -> + {Lcls,Vt1,St1} = from_icrt_cls(Cls, Vt0, St0), + {Lt,Vt2,St2} = from_expr(Timeout, Vt1, St1), + {Lb,Vt3,St3} = from_body(Body, Vt2, St2), + {'receive'|Lcls ++ 'after',Lt|Lb,Vt3,St3}; +from_expr({'catch',_,E}, Vt0, St0) -> + {Le,Vt1,St1} = from_expr(E, Vt0, St0), + {'catch',Le,Vt1,St1}; +from_expr({'try',_,Es,Scs,Ccs,As}, Vt, St) -> + from_try(Es, Scs, Ccs, As, Vt, St); +%% List/binary comprensions. +from_expr({lc,_,E,Qs}, Vt, St) -> + from_list_comp(E, Qs, Vt, St); +from_expr({bc,_,Seg,Qs}, Vt, St) -> + from_binary_comp(Seg, Qs, Vt, St); +%% Function calls. +from_expr({call,_,{remote,_,M,F},As}, Vt0, St0) -> %Remote function call + {Lm,Vt1,St1} = from_expr(M, Vt0, St0), + {Lf,Vt2,St2} = from_expr(F, Vt1, St1), + {Las,Vt3,St3} = from_expr_list(As, Vt2, St2), + {call,Lm,Lf|Las,Vt3,St3}; +from_expr({call,_,{atom,_,F},As}, Vt0, St0) -> %Local function call + {Las,Vt1,St1} = from_expr_list(As, Vt0, St0), + {F|Las,Vt1,St1}; +from_expr({call,_,F,As}, Vt0, St0) -> %F not an atom or remote + {Lf,Vt1,St1} = from_expr(F, Vt0, St0), + {Las,Vt2,St2} = from_expr_list(As, Vt1, St1), + {funcall,Lf|Las,Vt2,St2}; +from_expr({op,_,Op,A}, Vt0, St0) -> + {La,Vt1,St1} = from_expr(A, Vt0, St0), + {Op,La,Vt1,St1}; +from_expr({op,_,Op,L,R}, Vt0, St0) -> + {Ll,Vt1,St1} = from_expr(L, Vt0, St0), + {Lr,Vt2,St2} = from_expr(R, Vt1, St1), + {Op,Ll,Lr,Vt2,St2}. + +from_cons(Car, list|Es) -> list,Car|Es; +from_cons(Car, ) -> list,Car; +from_cons(Car, Cdr) -> cons,Car,Cdr. + +%% from_body(Expressions, VarTable, State) -> {Body,VarTable,State}. +%% Handle '=' specially here and translate into let containing rest +%% of body. + +from_body({match,_,_,_}=Match, Vt0,St0) -> %Last match + {Lm,Vt1,St1} = from_expr(Match, Vt0, St0), %Must return pattern as value + {Lm,Vt1,St1}; +from_body({match,_,P,E}|Es, Vt0, St0) -> + {Lp,Eqt,Vt1,St1} = from_pat(P, Vt0, St0), + {Le,Vt2,St2} = from_expr(E, Vt1, St1), + {Les,Vt3,St4} = from_body(Es, Vt2, St2), + Leg = from_eq_tests(Eqt), %Implicit guard tests + Lbody = from_add_guard(Leg, Le), + {'let',Lp|Lbody|Les,Vt3,St4}; +from_body(E|Es, Vt0, St0) -> + {Le,Vt1,St1} = from_expr(E, Vt0, St0),
View file
_service:tar_scm:lfe-1.3.tar.gz/src/lfe_types.erl -> _service:tar_scm:lfe-2.1.1.tar.gz/src/lfe_types.erl
Changed
@@ -1,4 +1,4 @@ -%% Copyright (c) 2016-2017 Robert Virding +%% Copyright (c) 2016-2021 Robert Virding %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -24,6 +24,7 @@ -module(lfe_types). +-export(is_type_decl/1). -export(format_error/1). -export(from_type_def/1,from_type_defs/1,to_type_def/2,to_type_defs/2, @@ -32,24 +33,27 @@ -export(from_func_spec_list/1,to_func_spec_list/2, check_func_spec_list/3). --export(is_predefined_type/2). - --compile(export_all). +%% -compile(export_all). -include("lfe.hrl"). %% format_error(Error) -> String. %% Do we really need this here? -format_error({bad_type,T}) -> +format_error({bad_type_def,T}) -> lfe_io:format1("bad ~w type definition", T); -format_error({type_syntax,T}) -> - lfe_io:format1(<<"bad ~w type">>, T); -format_error({undefined_type,{T,A}}) -> - lfe_io:format1(<<"type ~w/~w undefined">>, T,A); -format_error({bad_spec,S}) -> +format_error({bad_type_syntax,T}) -> + lfe_io:format1(<<"bad ~w type syntax">>, T); +format_error({bad_function_spec,S}) -> lfe_io:format1("bad function spec: ~w", S). +%% is_type_decl(Tag) -> boolean(). +%% Is Name a type declaration? + +is_type_decl(type) -> true; +is_type_decl(opaque) -> true; +is_type_decl(_Other) -> false. + %% from_type_def(AST) -> Def. %% Translate an Erlang type definition to LFE. This takes the Erlang %% AST form of a type definition and translates to the LFE type @@ -58,13 +62,18 @@ %% Our special cases. from_type_def({type,_L,union,Types}) -> %Special case union 'UNION'|from_type_defs(Types); -from_type_def({type,_L,tuple,any}) -> tuple; +from_type_def({type,_L,tuple,any}) -> %Special case tuple() -> (tuple) + tuple; +from_type_def({type,_L,tuple,Elems}) -> + list_to_tuple(from_type_defs(Elems)); from_type_def({type,_L,binary,Bits}) when Bits =/= -> - bitstring|from_type_defs(Bits); %Flip binary<->bitstring here + bitstring|from_type_defs(Bits); %Flip binary<->bitstring here %% from_type_def({type,_L,bitstring,}) -> bitstring,; +from_type_def({type,_L,map,any}) -> %Special case map() -> (map) + map; from_type_def({type,_L,map,Pairs}) -> - map|from_map_pairs(Pairs); -from_type_def({type,_L,record,{atom,_L,Name}|Fields}) -> + maps:from_list(from_map_pairs(Pairs)); +from_type_def({type,_L1,record,{atom,_L2,Name}|Fields}) -> record,Name|from_rec_fields(Fields); from_type_def({type,_L,'fun',Args,Ret}) -> lambda,from_lambda_args(Args),from_type_def(Ret); @@ -78,16 +87,20 @@ from_type_def({remote_type,_L,{atom,_,M},{atom,_,T},Args}) -> Type = list_to_atom(lists:concat(M,":",T)), Type|from_type_defs(Args); +%% Literal values. from_type_def({var,_L,Var}) -> Var; %A type variable from_type_def({atom,_L,Atom}) -> ?Q(Atom); %Literal atom -from_type_def({integer,_L,Int}) -> Int. %Literal integer +from_type_def({integer,_L,Int}) -> Int; %Literal integer +from_type_def({float,_L,Float}) -> Float. %Literal float from_type_defs(Ts) -> lists:map(fun from_type_def/1, Ts). from_map_pairs(Pairs) -> %% Lose distinction between assoc and exact pairs. - Fun = fun ({type,_L,_P,Types}) -> from_type_defs(Types) end, + Fun = fun ({type,_L,_P,Kt,Vt}) -> + {from_type_def(Kt),from_type_def(Vt)} + end, lists:map(Fun, Pairs). from_rec_fields(Fields) -> @@ -110,12 +123,14 @@ {type,Line,range,to_type_defs(I1,I2, Line)}; to_type_def(bitstring,I1,I2, Line) -> %Flip binary<->bitstring here {type,Line,binary,to_type_defs(I1,I2, Line)}; -to_type_def(tuple, Line) -> %Undefined tuple +to_type_def(tuple, Line) -> %Special case (tuple) -> tuple() {type,Line,tuple,any}; to_type_def(tuple|Args, Line) -> %Not a user defined type {type,Line,tuple,to_type_defs(Args, Line)}; -to_type_def(map|Pairs, Line) -> - {type,Line,map,to_map_pairs(Pairs, Line)}; +to_type_def(map, Line) -> %Special case (map) -> map() + {type,Line,map,any}; +to_type_def(map|Elems, Line) -> + {type,Line,map,to_map_pairs(to_pair_list(Elems), Line)}; to_type_def(record,Name|Fields, Line) -> {type,Line,record,to_lit(Name, Line)|to_rec_fields(Fields, Line)}; to_type_def(lambda,Args,Ret, Line) -> @@ -141,8 +156,15 @@ end, {Tag,Line,Type,Dargs} end; +to_type_def(Tup, Line) when is_tuple(Tup) -> + {type,Line,tuple,to_type_defs(tuple_to_list(Tup), Line)}; +to_type_def(Map, Line) when ?IS_MAP(Map) -> + ToPairs = to_map_pairs(maps:to_list(Map), Line), + {type,Line,map,ToPairs}; to_type_def(Val, Line) when is_integer(Val) -> %Literal integer value to_lit(Val, Line); +to_type_def(Val, Line) when is_float(Val) -> %Literal float value + to_lit(Val, Line); to_type_def(Val, Line) when is_atom(Val) -> %Variable {var,Line,Val}. @@ -150,12 +172,17 @@ lists:map(fun (D) -> to_type_def(D, Line) end, Ds). to_lit(Val, Line) when is_atom(Val) -> {atom,Line,Val}; -to_lit(Val, Line) when is_integer(Val) -> {integer,Line,Val}. +to_lit(Val, Line) when is_integer(Val) -> {integer,Line,Val}; +to_lit(Val, Line) when is_float(Val) -> {float,Line,Val}. + +to_pair_list(K,V|Rest) -> + {K,V}|to_pair_list(Rest); +to_pair_list() -> . to_map_pairs(Pairs, Line) -> %% Have lost distinction between assoc and exact pairs. - Fun = fun (Pair) -> - {type,Line,map_field_assoc,to_type_defs(Pair, Line)} + Fun = fun ({K,V}) -> + {type,Line,map_field_assoc,to_type_defs(K,V, Line)} end, Fun(P) || P <- Pairs . @@ -169,109 +196,117 @@ to_lambda_args(any, Line) -> {type,Line,any}; to_lambda_args(Args, Line) -> to_func_prod(Args, Line). -%% check_type_def(Def, KnownTypes, TypeVars) -> +%% check_type_defs(Defs, KnownRecords, TypeVars) -> +%% {ok,TypeVars} | {error,Error,TypeVars}. +%% check_type_def(Def, KnownRecords, TypeVars) -> %% {ok,TypeVars} | {error,Error,TypeVars}. %% Check a type definition. TypeVars is an orddict of variable names %% and usage counts. Errors returned are: -%% {bad_type,Type} - error in the type definition -%% {undefined_type,Type} - referring to an undefined type +%% {bad_type_syntax,Type} - error in the type syntax +%% {bad_type_def,Type} - error in the type definition %% Our special cases. -check_type_def('UNION'|Types, Kts, Tvs) -> - check_type_defs(Types, Kts, Tvs); -check_type_def(range,I1,I2, _Kts, Tvs) -> +check_type_def('UNION'|Types, Recs, Tvs) -> + check_type_defs(Types, Recs, Tvs); +check_type_def(range,I1,I2, _Recs, Tvs) -> if is_integer(I1) and is_integer(I2) and (I1 =< I2) -> {ok,Tvs}; - true -> type_syntax_error(range, Tvs) + true -> bad_type_syntax_error(range, Tvs) end; -check_type_def(tuple|Ts, Kts, Tvs) -> - check_type_defs(Ts, Kts, Tvs); -check_type_def(bitstring,I1,I2, _Kts, Tvs) -> +check_type_def(tuple|Ts, Recs, Tvs) -> + check_type_defs(Ts, Recs, Tvs); +check_type_def(bitstring,I1,I2, _Recs, Tvs) -> if is_integer(I1) and is_integer(I2) and (I1 >= 0) and (I2 >= 0) -> {ok,Tvs}; - true -> type_syntax_error(bitstring, Tvs) + true -> bad_type_syntax_error(bitstring, Tvs) end; -check_type_def(map|Pairs, Kts, Tvs) -> - check_map_pairs(Pairs, Kts, Tvs); -check_type_def(record,Name|Fields, Kts, Tvs) -> - if is_atom(Name) -> check_record_fields(Fields, Kts, Tvs); - true -> type_syntax_error(record, Tvs) - end; -check_type_def(lambda,Args,Ret, Kts, Tvs0) -> - case check_lambda_args(Args, Kts, Tvs0) of - {ok,Tvs1} -> check_type_def(Ret, Kts, Tvs1);
View file
_service:tar_scm:lfe-1.3.tar.gz/src/lfescript.erl -> _service:tar_scm:lfe-2.1.1.tar.gz/src/lfescript.erl
Changed
@@ -1,4 +1,4 @@ -%% Copyright (c) 2008-2016 Robert Virding +%% Copyright (c) 2008-2020 Robert Virding %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -25,6 +25,10 @@ -export(start/0,start/1). -export(run/1,run/2). +-include("lfe.hrl"). + +%% External API. + script_name() -> Sname|_ = init:get_plain_arguments(), Sname. @@ -34,10 +38,10 @@ -define(OK_STATUS, 0). -define(ERROR_STATUS, 127). -%% start() -> no_return(). -%% start(Options) -> no_return(). -%% run(CmdLine) -> no_return(). -%% run(CmdLine, Options) -> no_return(). +-spec start() -> no_return(). +-spec start(_Options) -> no_return(). +-spec run(_CmdLine) -> no_return(). +-spec run(_CmdLine, _Options) -> no_return(). %% Evaluate the LFE script. All errors which are caught here are %% internal errors. Start gets its arguments from the command line %% while run gets them as an argument. @@ -58,8 +62,7 @@ throw:Str -> lfe_io:format("lfescript: ~s\n", Str), halt(?ERROR_STATUS); - _:Reason -> - Stack = erlang:get_stacktrace(), %Need to get this first + ?CATCH(_, Reason, Stack) lfe_io:format("lfescript: Internal error: ~p\n", Reason), lfe_io:format("~p\n", Stack), halt(?ERROR_STATUS) @@ -142,7 +145,7 @@ %% expand_macros(Forms, File, Args, Lopts) -> {Forms,Fenv}. expand_macros(Fs0, File, _, _) -> - case lfe_macro:expand_forms(Fs0, lfe_env:new(), true, false) of + case lfe_macro:expand_fileforms(Fs0, lfe_env:new(), true, false) of {ok,Fs1,Fenv,Ws} -> list_warnings(File, Ws), {Fs1,Fenv}; @@ -163,13 +166,17 @@ %% make_env(Forms, File, Args, Lopts) -> FunctionEnv. -make_env(Fs, Fenv, _, _, _) -> - {Fbs,null} = lfe_lib:proc_forms(fun collect_form/3, Fs, null), +make_env(Forms, Fenv, _, _, _) -> + {Fbs,null} = lfe_lib:proc_forms(fun collect_function/3, Forms, null), lfe_eval:make_letrec_env(Fbs, Fenv). -collect_form('define-function',F,_Meta,Def, _, St) -> +collect_function('define-function',F,_Meta,Def, _, St) -> Ar = function_arity(Def), - {{F,Ar,Def},St}. + {{F,Ar,Def},St}; +%% Ignore everything else including types and eval-when-compile. +collect_function(_Form, _, St) -> + {,St}. + function_arity(lambda,As|_) -> length(As); function_arity('match-lambda',Pats|_|_) -> length(Pats). @@ -184,11 +191,10 @@ lfe_eval:expr(main,quote,Args, Fenv) catch %% Catch all exceptions in the code. - Class:Error -> - St = erlang:get_stacktrace(), %Need to get this first + ?CATCH(Class, Error, Stack) Skip = fun (_) -> false end, Format = fun (T, I) -> lfe_io:prettyprint1(T, 15, I, 80) end, - Cs = lfe_lib:format_exception(Class, Error, St, Skip, Format, 1), + Cs = lfe_lib:format_exception(Class, Error, Stack, Skip, Format, 1), io:put_chars(Cs), halt(?ERROR_STATUS) end.
View file
_service:tar_scm:lfe-2.1.1.tar.gz/src/scm.erl
Added
@@ -0,0 +1,276 @@ +%% Copyright (c) 2020 Robert Virding +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. + +%% File : scm.erl +%% Author : Robert Virding +%% Purpose : Lisp Flavoured Erlang scheme like macros + +-module(scm). + +-export('LFE-EXPAND-EXPORTED-MACRO'/3). + +-export(mbe_syntax_rules_proc/4,mbe_syntax_rules_proc/5, + mbe_match_pat/3,mbe_get_bindings/3,mbe_expand_pattern/3). + +-import(lists, member/2,map/2,all/2,any/2). + +%% 'LFE-EXPAND-EXPORTED-MACRO'(Name, Args, Env) -> {yes,Expansion} | no. +%% Explicitly define this function so we can call the begin, define, +%% define-syntax and let-syntax macros without having to include +%% scm.lfe. These are exactly equivalent to those macros. + +'LFE-EXPAND-EXPORTED-MACRO'(MacroName, MacroArgs, _Env) -> + case MacroName|MacroArgs of + %% These are easy. + 'begin'|Body -> + {yes,progn|Body}; + 'define',Head|Body -> + Exp = case lfe_lib:is_symb_list(Head) of + true -> + hd(Head),,lambda,tl(Head)|Body; + false -> + Head,,Body + end, + {yes,'define-function'|Exp}; + %% Now for the syntax macros. + 'define-syntax',Name,Def -> + {Meta,Mdef} = exp_syntax(Name, Def), + {yes,'define-macro',Name,Meta,Mdef}; + 'let-syntax',Defs|Body -> + Fun = fun (Name,Def) -> + {_,Def} = exp_syntax(Name, Def), + Name,Def + end, + Mdefs = map(Fun, Defs), + {yes,'let-macro',Mdefs|Body}; + defsyntax,Name|Rules -> + {Meta,Mdef} = exp_rules(Name, , Rules), + {yes,'define-macro',Name,Meta,Mdef}; + _ -> no + end. + + +%% exp_syntax(Name, Def) -> {Meta,Lambda | MatchLambda}. +%% N.B. New macro definition is function of 2 arguments, the whole +%% argument list of macro call, and the current macro environment. + +exp_syntax(Name, Def) -> + case Def of + macro|Cls -> + Mcls = map(fun (Pat|Body) -> Pat,'$ENV'|Body end, Cls), + {,'match-lambda'|Mcls}; + 'syntax-rules'|Rules -> + exp_rules(Name, , Rules) + end. + +%% exp_rules(Name, Keywords, Rules) -> {Meta,Lambda}. +%% Expand into call function which expands macro an invocation time, +%% this saves much space and costs us nothing. +%% N.B. New macro definition is function of 2 arguments, the whole +%% argument list of macro call, and the current macro environment. + +exp_rules(Name, Keywords, Rules) -> + {,lambda,args,'$ENV', + ':',scm,mbe_syntax_rules_proc, + quote,Name,quote,Keywords,quote,Rules,args}. + +%% Macro by Example +%% Proper syntax-rules which can handle ... ellipsis by Dorai Sitaram. +%% +%% While we extend patterns to include tuples and binaries as in +%% normal LFE we leave the keyword handling in even though it is +%% subsumed by quotes and not really used. + +%% To make it more lispy! +-define(car(L), hd(L)). +-define(cdr(L), tl(L)). +-define(cadr(L), hd(tl(L))). +-define(cddr(L), tl(tl(L))). + +-define(mbe_ellipsis(Car, Cddr), Car,'...'|Cddr). + +is_mbe_symbol(S) -> + is_atom(S) andalso not is_boolean(S). + +%% Tests if ellipsis pattern, (p ... . rest) +%% is_mbe_ellipsis(?mbe_ellipsis(_, _)) -> true; +%% is_mbe_ellipsis(_) -> false. + +mbe_match_pat(quote,P, E, _) -> P =:= E; +mbe_match_pat(tuple|Ps, tuple|Es, Ks) -> %Match tuple constructor + mbe_match_pat(Ps, Es, Ks); +mbe_match_pat(tuple|Ps, E, Ks) -> %Match literal tuple + case is_tuple(E) of + true -> mbe_match_pat(Ps, tuple_to_list(E), Ks); + false -> false + end; +mbe_match_pat(?mbe_ellipsis(Pcar, _), E, Ks) -> + case lfe_lib:is_proper_list(E) of + true -> + all(fun (X) -> mbe_match_pat(Pcar, X, Ks) end, E); + false -> false + end; +mbe_match_pat(Pcar|Pcdr, E, Ks) -> + case E of + Ecar|Ecdr -> + mbe_match_pat(Pcar, Ecar, Ks) andalso + mbe_match_pat(Pcdr, Ecdr, Ks); + _ -> false + end; +mbe_match_pat(Pat, E, Ks) -> + case is_mbe_symbol(Pat) of + true -> + case member(Pat, Ks) of + true -> Pat =:= E; + false -> true + end; + false -> Pat =:= E + end. + +mbe_get_ellipsis_nestings(Pat, Ks) -> + m_g_e_n(Pat, Ks). + +m_g_e_n(quote,_, _) -> ; +m_g_e_n(tuple|Ps, Ks) -> m_g_e_n(Ps, Ks); +m_g_e_n(?mbe_ellipsis(Pcar, Pcddr), Ks) -> + m_g_e_n(Pcar, Ks)|m_g_e_n(Pcddr, Ks); +m_g_e_n(Pcar|Pcdr, Ks) -> + m_g_e_n(Pcar, Ks) ++ m_g_e_n(Pcdr, Ks); +m_g_e_n(Pat, Ks) -> + case is_mbe_symbol(Pat) of + true -> + case member(Pat, Ks) of + true -> ; + false -> Pat + end; + false -> + end. + +mbe_ellipsis_sub_envs(Nestings, R) -> + ormap(fun (C) -> + case mbe_intersect(Nestings, ?car(C)) of + true -> ?cdr(C); + false -> false + end end, R). + +%% Return first value of F applied to elements in list which is not false. +ormap(F, H|T) -> + case F(H) of + false -> ormap(F, T); + V -> V + end; +ormap(_, ) -> false. + +mbe_intersect(V, Y) -> + case is_mbe_symbol(V) orelse is_mbe_symbol(Y) of + true -> V =:= Y; + false -> + any(fun (V0) -> + any(fun (Y0) -> mbe_intersect(V0, Y0) end, Y) + end, V) + end. + +%% mbe_get_bindings(Pattern, Expression, Keywords) -> Bindings. + +mbe_get_bindings(quote,_, _, _) -> ; +mbe_get_bindings(tuple|Ps, tuple|Es, Ks) -> %Tuple constructor + mbe_get_bindings(Ps, Es, Ks); +mbe_get_bindings(tuple|Ps, E, Ks) -> %Literal tuple + mbe_get_bindings(Ps, tuple_to_list(E), Ks); +mbe_get_bindings(?mbe_ellipsis(Pcar, _), E, Ks) -> + mbe_get_ellipsis_nestings(Pcar, Ks) | + map(fun (X) -> mbe_get_bindings(Pcar, X, Ks) end, E); +mbe_get_bindings(Pcar|Pcdr, Ecar|Ecdr, Ks) -> + mbe_get_bindings(Pcar, Ecar, Ks) ++ + mbe_get_bindings(Pcdr, Ecdr, Ks); +mbe_get_bindings(Pat, E, Ks) -> + case is_mbe_symbol(Pat) of + true ->
View file
_service:tar_scm:lfe-1.3.tar.gz/test/andor_SUITE.lfe -> _service:tar_scm:lfe-2.1.1.tar.gz/test/andor_SUITE.lfe
Changed
@@ -1,4 +1,4 @@ -;; Copyright (c) 2008-2013 Robert Virding +;; Copyright (c) 2008-2020 Robert Virding ;; ;; Licensed under the Apache License, Version 2.0 (the "License"); ;; you may not use this file except in compliance with the License. @@ -372,31 +372,41 @@ (line (test-pat 'true (COMB 'true 'true 'true))) ;; This next one crashed the compiler! - (line (test-pat (tuple 'EXIT (tuple 'if_clause _)) - (catch (COMB 'true 'blurf 'false)))) (line (test-pat 'false (COMB 'false 'blurf 'false))) (line (test-pat 'true (COMB 'false 'blurf 'true))) (line (test-pat 'true (COMB 'true 'true 'blurf))) + (test-pat 'false (simple-comb 'false 'false)) + (test-pat 'false (simple-comb 'false 'true)) + (test-pat 'false (simple-comb 'true 'false)) + (test-pat 'true (simple-comb 'true 'true)) + 'ok)) (defun comb (a b c) (let* ((r0 (orelse (andalso a b) c)) - (r1 (when (=:= r0 r1)) - (eif (orelse (andalso a b) c) 'true 'true 'false)) - (n0 (eif (not (orelse (andalso a b) c)) 'true 'true 'false)) - (n1 (when (=:= n0 n1)) - (id (not r1))) - (r2 (when (=:= r1 r2)) - (orelse (andalso a b) c)) - (r3 (when (=:= r2 r3)) - (eif (orelse (andalso a b) c) 'true 'true 'false)) - (n2 (when (=:= n1 n2)) - (id (not r3))) - (r4 (when (=:= r3 r4)) - (eif (orelse (andalso a b) c) 'true 'true 'false))) + (r1 (when (=:= r0 r1)) + (eif (orelse (andalso a b) c) 'true 'true 'false)) + (n0 (eif (not (orelse (andalso a b) c)) 'true 'true 'false)) + (n1 (when (=:= n0 n1)) + (id (not r1))) + (r2 (when (=:= r1 r2)) + (orelse (andalso a b) c)) + (r3 (when (=:= r2 r3)) + (eif (orelse (andalso a b) c) 'true 'true 'false)) + (n2 (when (=:= n1 n2)) + (id (not r3))) + (r4 (when (=:= r3 r4)) + (eif (orelse (andalso a b) c) 'true 'true 'false))) (id r4))) +(defun simple-comb (a b) + ;; Use res twice, to ensure that a careless optimization of 'not' + ;; doesn't leave res as a free variable. + (let* ((res (andalso a b)) + (_ (id res))) + res)) + ;; Test that a boolean expression in a case expression is properly ;; optimized (in particular, that the error behaviour is correct). (defun in_case
View file
_service:tar_scm:lfe-1.3.tar.gz/test/clj-tests.lfe -> _service:tar_scm:lfe-2.1.1.tar.gz/test/clj-tests.lfe
Changed
@@ -1,4 +1,4 @@ -;; Copyright (c) 2016 Eric Bailey +;; Copyright (c) 2016-2020 Eric Bailey ;; ;; Licensed under the Apache License, Version 2.0 (the "License"); ;; you may not use this file except in compliance with the License. @@ -16,7 +16,6 @@ ;; Author : Eric Bailey ;; Purpose : Test clj exports. - (defmodule clj-tests "Test clj exports.") @@ -30,11 +29,12 @@ ;;; defn (defun test-defn (f a def) - (let* ((forms `((defmodule dummy) ,def)) - (`#(ok (#(ok dummy ,beam))) (lfe_comp:forms forms)) - (`#(ok ,docs) (lfe_doc:get_module_docs beam))) - (lfe_io:format "~s/~w ~p~n" (list f a docs)) - (lfe_doc:function_docs f a docs))) + `#(ok #"doc")) + ;; (let* ((forms `((defmodule dummy) ,def)) + ;; (`#(ok (#(ok dummy ,beam))) (lfe_comp:forms forms)) + ;; (`#(ok ,docs) (lfe_doc:get_module_docs beam))) + ;; (lfe_io:format "~s/~w ~p~n" (list f a docs)) + ;; (lfe_doc:function_docs f a docs))) (deftest defn (are* f a def (ok? (is-match `#(ok ,_doc) (test-defn f a def))) @@ -77,7 +77,7 @@ 1540.0 (clj:->> (clj:seq 42) (lists:map (lambda (x) (math:pow x 2))) - (lists:filter (clj:comp #'clj:even?/1 #'round/1)) + (lists:filter (clj:comp #'even?/1 #'round/1)) (clj:take 10) (lists:foldl (fun + 2) 0)))) @@ -196,16 +196,16 @@ (is-equal (clj:identity (+ 1 2 3)) (c0 6)) (is-equal (clj:identity (quote foo)) (c0 'foo))) (let ((asin-result (funcall (clj:comp #'math:sin/1 #'math:asin/1) 0.5))) - (is-equal "0.5" (car (io_lib:format "~.1f" `(,asin-result))))) + (is-equal "0.5" (lists:flatten (io_lib:format "~.1f" `(,asin-result))))) (is-equal 1.5 (funcall (clj:comp `(,(lambda (x) (+ x 1)) ,#'math:sin/1 ,#'math:asin/1)) 0.5)) (is-equal '(1 2 3 4) - (lists:filter (clj:comp #'not/1 #'clj:zero?/1) + (lists:filter (clj:comp #'not/1 #'zero?/1) '(0 1 0 2 0 3 0 4))) (let ((asin-result (clj:comp #'math:sin/1 #'math:asin/1 0.5))) - (is-equal "0.5" (car (io_lib:format "~.1f" `(,asin-result)))))) + (is-equal "0.5" (lists:flatten (io_lib:format "~.1f" `(,asin-result)))))) (deftest partial (flet (;; (p0 (x) (funcall (clj:partial inc) x)) @@ -331,7 +331,7 @@ (deftest record? (is (clj:record? (make-foo) 'foo)) (is-not (clj:record? (make-foo) 'barf)) - ;; This fails due a bug: https://github.com/rvirding/lfe/issues/266 + ;; This fails due a bug: https://github.com/lfe/lfe/issues/266 ;; (is-not (clj:record? #(foo) 'foo)) (is-not (clj:record? 'foo)) (is-not (clj:record? 'a 'foo))) @@ -488,8 +488,8 @@ (IFF-MAPS (is (clj:empty? (call 'maps 'new))))) (deftest every? - (is-not (clj:every? #'clj:zero?/1 '(0 0 0 0 1))) - (is (clj:every? #'clj:zero?/1 '(0 0 0 0 0)))) + (is-not (clj:every? #'zero?/1 '(0 0 0 0 1))) + (is (clj:every? #'zero?/1 '(0 0 0 0 0)))) ;; Based on lists_SUITE. (deftest all? @@ -501,12 +501,16 @@ (is-not (lists:all (lambda (n) (=:= (rem n 2) 0)) l)))) (deftest any? - (is-not (clj:any? #'clj:zero?/1 '(1 1 1 1 1))) - (is (clj:any? #'clj:zero?/1 '(0 1 1 1 1)))) + (is-not (clj:any? #'zero?/1 '(1 1 1 1 1))) + (is (clj:any? #'zero?/1 '(0 1 1 1 1)))) (deftest not-any? - (is-not (clj:not-any? #'clj:zero?/1 '(0 1 1 1 1))) - (is (clj:not-any? #'clj:zero?/1 '(1 1 1 1 1)))) + (is-not (clj:not-any? #'zero?/1 '(0 1 1 1 1))) + (is (clj:not-any? #'zero?/1 '(1 1 1 1 1)))) + +;; Functional forms of clj module macros. +(defun zero? (x) (clj:zero? x)) +(defun even? (x) (clj:even? x)) (deftest element? (are* data (not (clj:element? 'z data))
View file
_service:tar_scm:lfe-1.3.tar.gz/test/eval_SUITE.lfe -> _service:tar_scm:lfe-2.1.1.tar.gz/test/eval_SUITE.lfe
Changed
@@ -1,4 +1,4 @@ -;; Copyright (c) 2008-2013 Robert Virding +;; Copyright (c) 2008-2020 Robert Virding ;; ;; Licensed under the Apache License, Version 2.0 (the "License"); ;; you may not use this file except in compliance with the License.
View file
_service:tar_scm:lfe-1.3.tar.gz/test/example_SUITE.lfe -> _service:tar_scm:lfe-2.1.1.tar.gz/test/example_SUITE.lfe
Changed
@@ -1,4 +1,4 @@ -;; Copyright (c) 2016 Eric Bailey +;; Copyright (c) 2016-2020 Eric Bailey ;; ;; Licensed under the Apache License, Version 2.0 (the "License"); ;; you may not use this file except in compliance with the License. @@ -27,5 +27,6 @@ (defun compile (config) (let* ((dpath (config 'data_dir config)) (efile (filename:join dpath "example.lfe"))) - (line (test-pat #(ok (#(ok example ()) #(ok another-example ())) ()) + ;; We can get warnings from the erlang compiler. + (line (test-pat `#(ok (#(ok example ,_) #(ok another-example ,_)) ()) (lfe_comp:file efile '(return))))))
View file
_service:tar_scm:lfe-1.3.tar.gz/test/guard_SUITE.lfe -> _service:tar_scm:lfe-2.1.1.tar.gz/test/guard_SUITE.lfe
Changed
@@ -1,4 +1,4 @@ -;; Copyright (c) 2008-2013 Robert Virding +;; Copyright (c) 2008-2020 Robert Virding ;; ;; Licensed under the Apache License, Version 2.0 (the "License"); ;; you may not use this file except in compliance with the License. @@ -212,7 +212,7 @@ (defun nested-not-1 (x y (when (not (and (or (> x y) (not (is_atom x))) - (or (is_atom y) (== x 3.4))))) + (or (is_atom y) (== x 3.4))))) 'true) (_ _ 'false)) @@ -240,14 +240,14 @@ (config (when (is_list config)) ;; ',' combinations of literal true/false. - (line (check (lambda () (eif (progn 'true 'false) 'ok 'true 'error)) 'error)) - (line (check (lambda () (eif (progn 'false 'true) 'ok 'true 'error)) 'error)) - (line (check (lambda () (eif (progn 'true 'true) 'ok)) 'ok)) - (line (check (lambda () (eif (progn 'false 'false) 'ok 'true 'error)) 'error)) + (line (check (lambda () (eif (and 'true 'false) 'ok 'true 'error)) 'error)) + (line (check (lambda () (eif (and 'false 'true) 'ok 'true 'error)) 'error)) + (line (check (lambda () (eif (and 'true 'true) 'ok)) 'ok)) + (line (check (lambda () (eif (and 'false 'false) 'ok 'true 'error)) 'error)) (line (check (lambda () (let (((tuple 'EXIT (tuple (tuple 'case_clause _) _)) - (catch (eif (progn 'true 'false) 'ok - (progn 'false 'true) 'ok - (progn 'false 'false) 'ok)))) + (catch (eif (and 'true 'false) 'ok + (and 'false 'true) 'ok + (and 'false 'false) 'ok)))) 'exit)) 'exit)) @@ -257,45 +257,45 @@ (atuple (id #(a b c)))) ;; ',' combinations of true/false in variables. - (line (check (lambda () (eif (progn true false) 'ok 'true 'error)) 'error)) - (line (check (lambda () (eif (progn false true) 'ok 'true 'error)) 'error)) - (line (check (lambda () (eif (progn true true) 'ok 'true 'error)) 'ok)) + (line (check (lambda () (eif (and true false) 'ok 'true 'error)) 'error)) + (line (check (lambda () (eif (and false true) 'ok 'true 'error)) 'error)) + (line (check (lambda () (eif (and true true) 'ok 'true 'error)) 'ok)) ;; These used to crash the compiler! - (line (check (lambda () (eif (progn false false) 'ok 'true 'error)) 'error)) + (line (check (lambda () (eif (and false false) 'ok 'true 'error)) 'error)) (line (check (lambda () (let (((tuple 'EXIT (tuple (tuple 'case_clause _) _)) - (catch (eif (progn true false) 'ok - (progn false true) 'ok - (progn false false) 'ok)))) + (catch (eif (and true false) 'ok + (and false true) 'ok + (and false false) 'ok)))) 'exit)) 'exit)) ;; ',' combinations of true/false, and non-boolean in variables. - (line (check (lambda () (eif (progn true glurf) 'ok 'true 'error)) 'error)) - (line (check (lambda () (eif (progn glurf true) 'ok 'true 'error)) 'error)) - (line (check (lambda () (eif (progn true true) 'ok)) 'ok)) + (line (check (lambda () (eif (and true glurf) 'ok 'true 'error)) 'error)) + (line (check (lambda () (eif (and glurf true) 'ok 'true 'error)) 'error)) + (line (check (lambda () (eif (and true true) 'ok)) 'ok)) ;; These used to crash the compiler! - (line (check (lambda () (eif (progn glurf glurf) 'ok 'true 'error)) 'error)) + (line (check (lambda () (eif (and glurf glurf) 'ok 'true 'error)) 'error)) (line (check (lambda () (let (((tuple 'EXIT (tuple (tuple 'case_clause _) _)) - (catch (eif (progn true glurf) 'ok - (progn glurf true) 'ok - (progn glurf glurf) 'ok)))) + (catch (eif (and true glurf) 'ok + (and glurf true) 'ok + (and glurf glurf) 'ok)))) 'exit)) 'exit)) ;; ',' combinations of true/false with errors. - (line (check (lambda () (eif (progn true (element 42 atuple)) 'ok + (line (check (lambda () (eif (and true (element 42 atuple)) 'ok 'true 'error)) 'error)) - (line (check (lambda () (eif (progn (element 42 atuple) true) 'ok + (line (check (lambda () (eif (and (element 42 atuple) true) 'ok 'true 'error)) 'error)) - (line (check (lambda () (eif (progn true true) 'ok)) 'ok)) - (line (check (lambda () (eif (progn (element 42 atuple) + (line (check (lambda () (eif (and true true) 'ok)) 'ok)) + (line (check (lambda () (eif (and (element 42 atuple) (element 42 atuple)) 'ok 'true 'error)) 'error)) (line (check (lambda () (let (((tuple 'EXIT (tuple (tuple 'case_clause _) _)) - (catch (eif (progn true (element 42 atuple)) 'ok - (progn (element 42 atuple) true) 'ok - (progn (element 42 atuple) + (catch (eif (and true (element 42 atuple)) 'ok + (and (element 42 atuple) true) 'ok + (and (element 42 atuple) (element 42 atuple)) 'ok)))) 'exit)) 'exit))) @@ -968,15 +968,18 @@ (config (when (is_list config)) (let ((t (id #(type integers 23 42)))) (line (test-pat 65 (eif (andalso (=:= (element 1 t) 'type) - (=:= (tuple_size t) 4) - (=:= (element 2 t) 'integers)) - (+ (element 3 t) (element 4 t)) - 'true 'error))) - (line (test-pat 65 (case () - (() (andalso (=:= (element 1 t) 'type) - (=:= (tuple_size t) 4) - (=:= (element 2 t) 'integers)) - (+ (element 3 t) (element 4 t)))))) + (=:= (tuple_size t) 4) + (=:= (element 2 t) 'integers)) + (+ (element 3 t) (element 4 t)) + 'true 'error))) + ;; XXX The following causes this test to fail on Erlang 22; we're not sure + ;; why. Here's the ticket: + ;; * https://github.com/lfe/lfe/issues/386 + ;; (line (test-pat 65 (case () + ;; (() (andalso (=:= (element 1 t) 'type) + ;; (=:= (tuple_size t) 4) + ;; (=:= (element 2 t) 'integers)) + ;; (+ (element 3 t) (element 4 t)))))) (line (test-pat 42 (basic-rt #(type integers 40 2)))) (line (test-pat 5.0 (basic-rt #(vector #(3.0 4.0))))) (line (test-pat 20 (basic-rt '(+ 3 7)))) @@ -990,29 +993,29 @@ (line (test-pat 'error (basic-rt ()))) (let ((rel-prod-body (lambda (r1 r2) - (eif (andalso (=:= (: erlang size r1) 3) - (=:= (: erlang element 1 r1) 'Set) - (=:= (: erlang size r2) 3) - (=:= (: erlang element 1 r2) 'Set)) - 'ok)))) + (eif (andalso (=:= (: erlang size r1) 3) + (=:= (: erlang element 1 r1) 'Set) + (=:= (: erlang size r2) 3) + (=:= (: erlang element 1 r2) 'Set)) + 'ok)))) (line (test-pat 'ok (funcall rel-prod-body #(Set a b) #(Set a b))))) ;; 'andalso'/'orelse' with calls known to fail already at compile time. ;; Used to crash the code generator. (let (('error (funcall (lambda () - (let ((r #(vars true))) - (eif (andalso (is_record r 'vars 2) - (element 99 r)) - 'ok - 'true 'error))) - )) - ('error (funcall (lambda (x) - (let ((l #(a b c))) - (eif (andalso (is_list x) - (> (length l) 4)) - 'ok - 'true 'error))) - ()))) + (let ((r #(vars true))) + (eif (andalso (is_record r 'vars 2) + (element 99 r)) + 'ok + 'true 'error))) + )) + ('error (funcall (lambda (x) + (let ((l #(a b c))) + (eif (andalso (is_list x) + (> (length l) 4)) + 'ok + 'true 'error))) + ()))) ()) 'ok))) @@ -1024,7 +1027,7 @@ (t (when (andalso (is_tuple t) (=:= (tuple_size t) 2) (=:= (element 1 t) 'vector))) (let (((tuple x y) (element 2 t))) - (eif (progn (is_float x) (is_float y)) (: math sqrt (+ (* x x) (* y y)))) + (eif (and (is_float x) (is_float y)) (: math sqrt (+ (* x x) (* y y)))) )) ((list '+ a b) (* (id (+ a b)) 2))
View file
_service:tar_scm:lfe-2.1.1.tar.gz/test/maps-tests.lfe
Added
@@ -0,0 +1,32 @@ +;; Copyright (c) 2021 Duncan McGreggor +;; +;; Licensed under the Apache License, Version 2.0 (the "License"); +;; you may not use this file except in compliance with the License. +;; You may obtain a copy of the License at +;; +;; http://www.apache.org/licenses/LICENSE-2.0 +;; +;; Unless required by applicable law or agreed to in writing, software +;; distributed under the License is distributed on an "AS IS" BASIS, +;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +;; See the License for the specific language governing permissions and +;; limitations under the License. + +;; File : maps-tests.lfe +;; Author : Duncan McGreggor +;; Purpose : Tests map functions support across multiple versions of Erlang. + +(defmodule maps-tests + "Test various map functions.") + +(include-file "ltest-macros.lfe") + +(defun test-data () + '#m(a 1 + b 2)) + +(deftest mref + (is-equal 1 (mref (test-data) 'a))) + +(deftest map-get + (is-equal 2 (map-get (test-data) 'b)))
View file
_service:tar_scm:lfe-1.3.tar.gz/test/ms_transform_SUITE.lfe -> _service:tar_scm:lfe-2.1.1.tar.gz/test/ms_transform_SUITE.lfe
Changed
@@ -1,4 +1,4 @@ -;; Copyright (c) 2008-2013 Robert Virding +;; Copyright (c) 2008-2020 Robert Virding ;; ;; Licensed under the Apache License, Version 2.0 (the "License"); ;; you may not use this file except in compliance with the License. @@ -6,7 +6,7 @@ ;; ;; http://www.apache.org/licenses/LICENSE-2.0 ;; -;; Unless required by applicable law or agreed to in writing, software +;; Unless required by applicable law or agreed tfo in writing, software ;; distributed under the License is distributed on an "AS IS" BASIS, ;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ;; See the License for the specific language governing permissions and @@ -24,32 +24,37 @@ ;; Note that some of these tests are not LFE specific but more general ;; guard tests but we include them anyway for completeness. ;; -;; As match-spec is a macro we can expand it directly inline which -;; means that many errors/inconsistencies will be detected at compile +;; As ets-ms is a macro we can expand it directly inline which means +;; that many errors/inconsistencies will be detected at compile ;; time. Should we write it to a file or in memory and compile at ;; run-time? +;; +;; NOTE: ets-ms generates a pattern so when testing the pattern with +;; test-pat it *must* be used in the pattern not in the value. (include-file "test_server.lfe") (defmodule ms_transform_SUITE (export (all 0) (suite 0) (groups 0) (init_per_suite 1) (end_per_suite 1) - (init_per_group 2) (end_per_group 2) - (init_per_testcase 2) (end_per_testcase 2) - (basic_ets 1) (basic_dbg 1) (from_shell 1) (records 1) - (record_index 1) (multipass 1) (top_match 1) (old_guards 1) - (autoimported 1) (semicolon 1) (bitsyntax 1) - (record_defaults 1) (andalso_orelse 1) - (float_1_function 1) (action_function 1) (warnings 1) - )) + (init_per_group 2) (end_per_group 2) + (init_per_testcase 2) (end_per_testcase 2)) + (export (basic_ets 1) (basic_dbg 1) (from_shell 1) (records 1) + (record_index 1) (multipass 1) (top_match 1) (old_guards 1) + (autoimported 1) (semicolon 1) (bitsyntax 1) + (record_defaults 1) (andalso_orelse 1) + (float_1_function 1) (action_function 1) + (warnings 1) (no_warnings 1))) (defmacro MODULE () `'ms_transform_SUITE) (defun all () ;; (: test_lib recompile (MODULE)) - (list 'basic_ets 'basic_dbg 'from_shell 'records - 'record_index 'multipass 'top_match 'old_guards - 'autoimported 'semicolon 'bitsyntax 'record_defaults - 'andalso_orelse 'float_1_function 'action_function 'warnings)) + (list 'from_shell 'basic_ets 'basic_dbg 'records + 'record_index 'multipass 'bitsyntax 'record_defaults + 'andalso_orelse 'float_1_function 'action_function + 'warnings 'no_warnings 'top_match 'old_guards + 'autoimported 'semicolon + )) ;;(defun suite () (list (tuple 'ct_hooks (list 'ts_install_cth)))) (defun suite () ()) @@ -72,43 +77,143 @@ (let ((dog (config 'watchdog config))) (: test_server timetrap_cancel dog))) +(defun warnings + ('suite ()) + ('doc '"Check that shadowed variables in fun head generate warning") + (config (when (is_list config)) + ;; Not relevant to LFE. + 'ok)) + +(defun no_warnings + ('suite ()) + ('doc '"Check that variables bound in other function clauses don't generate warning.") + (config (when (is_list config)) + ;; Not relevant to LFE. + 'ok)) + +(defun andalso_orelse + ('suite ()) + ('doc '"Tests that andalso and orelse are allowed in guards.") + (config (when (is_list config)) + (setup config) + ;; {{'$1','$2'}, + ;; {'and',{is_integer,'$1'},{'>',{'+','$1',5},'$2'}}, + ;; {'andalso','$1','$2'}} + (test-pat '(#(#($1 $2) + (#(and #(is_integer $1) #(> #(+ $1 5) $2))) + (#(andalso $1 $2)))) + (ets-ms ((tuple a b) + (when (and (is_integer a) (> (+ a 5) b))) + (andalso a b)))) + ;; {{'$1','$2'}, + ;; {'or',{is_atom,'$1'},{'>',{'+','$1',5},'$2'}}, + ;; {'orelse','$1','$2'}} + (test-pat '(#(#($1 $2) + (#(or #(is_atom $1) #(> #(+ $1 5) $2))) + (#(orelse $1 $2)))) + (ets-ms ((tuple a b) + (when (or (is_atom a) (> (+ a 5) b))) + (orelse a b)))) + ;; {{'$1','$2'}, + ;; {'andalso',{is_integer,'$1'},{'>',{'+','$1',5},'$2'}}, + ;; '$1'} + (test-pat '(#(#($1 $2) + (#(andalso #(is_integer $1) #(> #(+ $1 5) $2))) + ($1))) + (ets-ms ((tuple a b) + (when (andalso (is_integer a) (> (+ a 5) b))) + a))) + ;; {{'$1','$2'}, + ;; {'orelse',{is_atom,'$1'},{'>',{'+','$1',5},'$2'}}, + ;; '$1'} + (test-pat '(#(#($1 $2) + (#(orelse #(is_atom $1) #(> #(+ $1 5) $2))) + ($1))) + (ets-ms ((tuple a b) + (when (orelse (is_atom a) (> (+ a 5) b))) + a))) + + 'ok)) + +(defun bitsyntax + ('suite ()) + ('doc '"Tests that bitsyntax works and does not work where appropriate") + (config (when (is_list config)) + (line (setup config)) + (line (let ((a 27)) + (test-pat '(#(_ () (#b(0 27 0 27)))) + (ets-ms (_ (binary (a (size 16)) (27 (size 16))))) + ))) + (line (let ((a 13)) ;Must fit in 4 bits! + (test-pat '(#(#(#b(15 47) $1 $2) + (#(=:= $1 #b(0 13)) #(=:= $2 #b(27 28 19))) + (#b(220 0 13)))) + (ets-ms ((tuple #b(15 47) b c) + (when (=:= b (binary (a (size 16)))) + (=:= c (binary 27 28 19))) + (binary (a (size 4)) (12 (size 4)) + (13 (size 16))))) + ))) + + 'ok)) + +(defrecord d a b c (d 'foppa)) ;Changed record name from a + +(defun record_defaults + ('suite ()) + ('doc '"Tests that record defaults works") + (config (when (is_list config)) + (line (setup config)) + ;; {{<<27>>,{a,5,'$1',hej,hej}}, + ;; , + ;; {{a,hej,{'*','$1',2},flurp,flurp}}} + (line (test-pat '(#(#(#b(27) #(d 5 $1 hej hej)) + () + (#(#(d hej #(* $1 2) flurp flurp))))) + (ets-ms ((tuple #b(27) (match-d a 5 b b _ 'hej)) + (make-d a 'hej b (* b 2) _ 'flurp))))) + + 'ok)) + (defun basic_ets ('suite ()) ('doc '"Tests basic ets:fun2ms") (config (when (is_list config)) (line (setup config)) - (line (test-pat '(#(#(a b) () (true))) (match-spec ((tuple 'a 'b) 'true)))) + (line (test-pat '(#(#(a b) () (true))) + (ets-ms ((tuple 'a 'b) 'true)))) (line (test-pat '(#(#($1 foo) (#(is_list $1)) (#(#(#(hd $1) $_)))) - #(#($1 $1) (#(is_tuple $1)) (#(#(#(element 1 $1) $*))))) - (match-spec ((tuple x 'foo) (when (is_list x)) - (tuple (hd x) (object))) - ((tuple x x) (when (is_tuple x)) - (tuple (element 1 x) (bindings)))) - )) + #(#($1 $1) (#(is_tuple $1)) (#(#(#(element 1 $1) $*))))) + (ets-ms ((tuple x 'foo) (when (is_list x)) + (tuple (hd x) (object))) + ((tuple x x) (when (is_tuple x)) + (tuple (element 1 x) (bindings)))) + )) (line (test-pat '(#(#($1 $2) () (#(#($2 $1))))) - (match-spec ((tuple a b) (tuple b a))))) + (ets-ms ((tuple a b) (tuple b a))))) (line (test-pat '(#(#($1 $2) () (($2 $1)))) - (match-spec ((tuple a b) (list b a))))) + (ets-ms ((tuple a b) (list b a))))) 'ok)) (defun basic_dbg
View file
_service:tar_scm:lfe-2.1.1.tar.gz/test/prop_lfe_docs.erl
Added
@@ -0,0 +1,169 @@ +%% Copyright (c) 2016-2020 Eric Bailey +%% +%% Licensed under the Apache License, Version 2.0 (the "License"); +%% you may not use this file except in compliance with the License. +%% You may obtain a copy of the License at +%% +%% http://www.apache.org/licenses/LICENSE-2.0 +%% +%% Unless required by applicable law or agreed to in writing, software +%% distributed under the License is distributed on an "AS IS" BASIS, +%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +%% See the License for the specific language governing permissions and +%% limitations under the License. + +%% File : prop_lfe_docs.erl +%% Author : Eric Bailey, Robert Virding +%% Purpose : PropEr tests for the lfe_docs module. + +%% This module is a modified version of the older test module for +%% lfe_doc written by Eric Bailey. + +-module(prop_lfe_docs). + +-export(prop_define_lambda/0,prop_define_match/0). + +-include_lib("proper/include/proper.hrl"). + +-include("lfe_docs.hrl"). + +%%%=================================================================== +%%% Properties +%%%=================================================================== + +%% These only test the formats of the saved data. + +prop_define_lambda() -> ?FORALL(Def, define_lambda(), validate(Def)). + +prop_define_match() -> ?FORALL(Def, define_match(), validate(Def)). + +validate({'define-function',Name,_Doc,Def,_}=Func) -> + validate_function(Name, function_arity(Def), Func); +validate({'define-macro',Name,_Doc,_Def,_}=Mac) -> + validate_macro(Name, Mac). + +function_arity(lambda,Args|_) -> length(Args); +function_arity('match-lambda',Pat|_|_) -> length(Pat). + +validate_function(Name, Arity, {_Define,_Name,_Meta,_Def,Line}=Func) -> + Info = export_all_funcs(),Func, %Add function export + case lfe_docs:make_docs_info(Info, ) of + {ok,#docs_v1{docs=Fdoc}} -> + {{function,N,A},Anno,_,_,_} = Fdoc, + (Line =:= Anno) and (Name =:= N) and (Arity =:= A); + _ -> false + end. + +validate_macro(Name, {_Define,_Name,_Meta,_Lambda,Line}=Mac) -> + Info = export_macro(Name),Mac, %Add macro export + case lfe_docs:make_docs_info(Info, ) of + {ok,#docs_v1{docs=Mdoc}} -> + {{macro,N,_},Anno,_,_,_} = Mdoc, + (Line =:= Anno) and (Name =:= N); + _ -> false + end. + +export_all_funcs() -> {'extend-module',,export,all,1}. + +export_macro(Mac) -> {'extend-module',,'export-macro',Mac,1}. + +%%%=================================================================== +%%% Definition shapes +%%%=================================================================== + +define_lambda() -> + {'define-function',atom(),meta_with_doc(),lambda(),line()}. + +define_match() -> + ?LET(D, define(), {D,atom(),meta_with_doc(),'match-lambda'(D),line()}). + + +%%%=================================================================== +%%% Custom types +%%%=================================================================== + +%%% Definitions + +define() -> oneof('define-function','define-macro'). + +lambda() -> lambda,arglist_simple()|body(). + +'match-lambda'('define-function') -> + 'match-lambda'|non_empty(list(function_pattern_clause())); +'match-lambda'('define-macro') -> + 'match-lambda'|non_empty(list(macro_pattern_clause())). + +arglist_simple() -> list(atom()). + +body() -> non_empty(list(form())). + +form() -> union(form_elem(),atom()|list(form_elem())). + +form_elem() -> union(non_string_term(),printable_string(),atom()). + +meta_with_doc() -> doc,docstring(). + +docstring() -> printable_string(). + +line() -> pos_integer(). + + +%%% Patterns + +pattern() -> union(non_string_term(),printable_string(),pattern_form()). + +pattern_form() -> + oneof('=','++*',, + backquote,quote, + binary,cons,list,map,tuple, + match_fun()) + | body(). + +match_fun() -> 'match-record'. + +macro_pattern_clause() -> pattern_clause(rand_arity(), true). + +function_pattern_clause() -> pattern_clause(rand_arity(), false). + +pattern_clause(Arity, Macro) -> + arglist_patterns(Arity, Macro)|oneof(guard(),form())|body(). + +arglist_patterns(Arity, false) -> vector(Arity, pattern()); +arglist_patterns(Arity, true) -> vector(Arity, pattern()),'$ENV'. + +guard() -> 'when'|non_empty(list(union(logical_clause(),comparison()))). + + +%%% Logical clauses + +logical_clause() -> + X = union(atom(),comparison()), + logical_operator(),X|non_empty(list(X)). + +logical_operator() -> oneof('and','andalso','or','orelse'). + + +%%% Comparisons + +comparison() -> comparison_operator(),atom()|list(atom()). + +comparison_operator() -> oneof('==','=:=','=/=','<','>','=<','>='). + + +%%% Strings and non-strings + +non_string_term() -> + union(atom(),number(),,bitstring(),binary(),boolean(),tuple()). + +printable_char() -> union(integer(32, 126),integer(160, 255)). + +printable_string() -> list(printable_char()). + + +%%% Rand compat + +-ifdef(NEW_RAND). +rand_arity() -> rand:uniform(10). +-else. +rand_arity() -> random:uniform(10). +-endif.
View file
_service:tar_scm:lfe-1.3.tar.gz/test/test_server.lfe -> _service:tar_scm:lfe-2.1.1.tar.gz/test/test_server.lfe
Changed
@@ -1,4 +1,4 @@ -;; Copyright (c) 2008-2013 Robert Virding +;; Copyright (c) 2008-2020 Robert Virding ;; ;; Licensed under the Apache License, Version 2.0 (the "License"); ;; you may not use this file except in compliance with the License. @@ -23,10 +23,10 @@ (,pat val)) val)) -;; We don't have any sensible line numbers to save so we save form. -(defmacro line (expr) - `(progn (put 'test_server_loc (tuple (MODULE) ',expr)) - ,expr)) +;; Backwards compatibility for test_server test suites only. +;; DO NOT USE IN NEW TEST SUITES. + +(defmacro line (expr) expr) (defmacro config args `(: test_server lookup_config . ,args))
Locations
Projects
Search
Status Monitor
Help
Open Build Service
OBS Manuals
API Documentation
OBS Portal
Reporting a Bug
Contact
Mailing List
Forums
Chat (IRC)
Twitter
Open Build Service (OBS)
is an
openSUSE project
.
浙ICP备2022010568号-2