~swisschili/bluejay

a89ee44a31c681be10b2757dc5274c1d87e467e2 — swissChili 9 months ago 9d151e6
Add AND and OR
2 files changed, 74 insertions(+), 10 deletions(-)

M doc/lisp_reference/lisp_reference.tex
M src/lisp/compiler.dasc
M doc/lisp_reference/lisp_reference.tex => doc/lisp_reference/lisp_reference.tex +13 -4
@@ 46,6 46,7 @@
    \fbox{#1}}}}
\newcommand{\opt}[2]{\text{$[$}\param{#1}\default{#2}\text{$]$}}
\newcommand{\mut}[1]{\text{$\widetilde{#1}$}}
\newcommand{\mighteval}[1]{\text{$\widehat{#1}$}}
\newcommand{\super}[1]{\text{$ ^{#1} $}}

\newcommand{\optlist}[1]{\text{\(


@@ 78,16 79,17 @@ This document provides a brief reference to the Bluejay Lisp language and standa

The following text styles and symbols are used within this document to indicate particular values or meanings:

\begin{tabular}[t]{p{0.2\linewidth} p{0.7\linewidth}}
\begin{tabular}[t]{p{0.2\linewidth} p{0.64\linewidth}}
    \func{cons} & A function ``cons.'' \\
    \const{\plus{}foo\plus} & A constant ``\plus{}foo\plus.'' \\
    \var{\earmuff{}bar\earmuff} & A global variable ``\earmuff{}bar\earmuff''. \\
    \reader{baz} & A reader macro ``baz.'' \\
    \mac{quux} & A macro ``quux.'' \\
    \param{parameter} & A function argument ``parameter`` \\
    \param{parameter} & A function argument ``parameter'' \\
    \opt{var}{123} & An optional function argument ``var'' with the default value ``123.'' \\
    \param{args}\more & ``args'' represents the rest of the items in the list. \\
    \mut{\param{mut}} & A function argument ``mut'' that might be mutated. \\
    \mighteval{\param{maybe}} & ``maybe'' may or may not be evaluated. \\
    \ret{value} & Indicates that a form will evaluate to ``value''. \\
    \type{integer} & The type ``integer''. \\
    \optlist{\text{a}\\\text{b}} & One of ``a'' or ``b.''


@@ 144,6 146,13 @@ The following text styles and symbols are used within this document to indicate 
    Evaluate \param{forms} from first to last, finally returning \ret{the last form}.
}

\definition{
    (\mac{and} \param{first} \param{\mighteval{rest}}\more)\index{and} \\
    (\mac{or} \param{first} \param{\mighteval{rest}}\more)\index{or}
}{
    Short circuiting $\land$ and $\lor$, respectively. Return the first value that is \nil{} or truthy, respectively, or the last value if all are truthy/\nil{}.
}

\section{Numbers}

\subsection{Integers}


@@ 166,7 175,7 @@ The following text styles and symbols are used within this document to indicate 
\section{Function Manipulation}

\definition{
    (\func{funcall} \param{function} \param{args}\more)\index{funcall} \\
    (\func{funcall} \param{args}\more)\index{funcall} \\
    (\func{apply} \param{function} \param{args})\index{apply}
}{
    Call the \type{closure} or \type{function-object} \param{function} with \param{args} and evaluate to \ret{its result}. An error occurs if \param{args} are not acceptable.


@@ 176,7 185,7 @@ The following text styles and symbols are used within this document to indicate 
    (\mac{function} \param{function-name})\index{function} \\
    \reader{\#\textquotesingle}\param{function-name}\index{\#\textquotesingle}
}{
    Create a \ret{\type{function-object} from an existing function}. \param{function} must be a symbol literal at compile time.
    Create a \ret{\type{function-object} from an existing function or macro}. \param{function} must be a symbol literal at compile time.
}

\definition{

M src/lisp/compiler.dasc => src/lisp/compiler.dasc +61 -6
@@ 220,7 220,7 @@ void compile_tl(value_t val, struct environment *env, char *fname)
		enum namespace namespace = NS_FUNCTION;

		if (symstreq(form, "defmacro"))
		namespace = NS_MACRO;
			namespace = NS_MACRO;

		struct local local;
		struct args *a;


@@ 396,7 396,7 @@ void compile_backquote(struct environment *env, struct local *local,
				// Remove unnecessary pop
				| push eax;
			}
				| pop eax;
			| pop eax;
		}
	}
}


@@ 485,6 485,37 @@ void compile_expression(struct environment *env, struct local *local,
				compile_expression(env, local, elt(args, 2), tail, Dst);
			|=>after_label:;
		}
		else if (symstreq(fsym, "and") || symstreq(fsym, "or"))
		{
			bool or = symstreq(fsym, "or"); // false == and

			// Boolean and and or, short circuit like &&/||
			if (nargs < 1)
			{
				err_at(val, "and & or require at least 1 argument.");
			}

			int after = nextpc(local, Dst);

			for (; !nilp(args); args = cdr(args))
			{
				compile_expression(env, local, car(args), false, Dst);
				if (!nilp(cdr(args)))
				{
					| cmp eax, nil;
					if (or)
					{
						| jne =>early;
					}
					else
					{
						| je =>early;
					}
				}
			}

			|=>after:;
		}
		else if (symstreq(fsym, "progn"))
		{
			for (value_t val = args; !nilp(val); val = cdr(val))


@@ 563,11 594,26 @@ void compile_expression(struct environment *env, struct local *local,
				    "compile time");
			}

			struct function *f =
			    find_function(env, (char *)(car(args) ^ SYMBOL_TAG));
			value_t closure = create_closure(f->code_ptr, f->args, 0);
			char *name = (char *)(car(args) ^ SYMBOL_TAG);

			if (!strcmp(name, local->current_function_name))
			{
				| push 0;
				| push local->args;
				| push <1;
				| call_extern create_closure;
			}
			else
			{
				struct function *f = find_function(env, name);

			| mov eax, (closure);
				if (!f)
				{
					err_at(val, "Function `%s' does not exist", (char *)(car(args) ^ SYMBOL_TAG));
				}
				value_t closure = create_closure(f->code_ptr, f->args, 0);
				| mov eax, (closure);
			}
		}
		else if (symstreq(fsym, "list"))
		{


@@ 808,6 854,15 @@ void compile_expression(struct environment *env, struct local *local,
			compile_variable(v, Dst);
		}
	}
	else if (closurep(val))
	{
		| mov eax, val;
	}
	else
	{
		printval(val, 1);
		err_at(val, "Don't know how to compile this, sorry.");
	}
}

struct variable *add_variable(struct local *local, enum var_type type,