fix bad bootstrap bug; generic append, reverse, concat (replacing cat and append*); working on documentation
parent
b666a3c3e0
commit
8b496e60ff
|
@ -0,0 +1,222 @@
|
|||
\documentclass{article}
|
||||
\author{Daniel Ehrenberg}
|
||||
\title{Comparing Factor to Other Languages}
|
||||
\usepackage{alltt}
|
||||
|
||||
\begin{document}
|
||||
\maketitle
|
||||
|
||||
\begin{abstract}
|
||||
Factor is a new programming language created by Slava Pestov. Although it is a great new collection of ideas, much of it comes from other languages. If you know certain other languages, like Joy, Forth, or Lisp, it can be much easier to learn Factor when told the relation between the two. This document attempts to show people how Factor compares to other languages. This is not a tutorial, but rather a first look at Factor for people who already program.
|
||||
\end{abstract}
|
||||
|
||||
\section{Forth}
|
||||
|
||||
In many ways, Factor is just like Forth, but with a few additional features: garbage collection, dynamic types, error handling and an object system. If you're a Forth user, you're probably opposed to these features. But the way Factor does these things doesn't (in my experience) make things any more difficult or inextensible for the programmer.
|
||||
|
||||
Factor uses essentially the same parsing model as Forth, except there is no interpret mode. That said, if you execute code that has been only parsed, nothing more, it is considered interpreting. In Factor, parsing words don't compile code in as they do in Forth; instead, they merely cons onto a list, building a quotation which can be called. Compiling code entails complex multi-pass manipulation of this quotation, and the resulting machine code is stored in memory or in an image. Factor revolves around executing quotations, which are linked lists of words and data, essentially the source code that has merely been parsed. The return stack consists of these, executing them one word at a time (when Factor is interpreted).
|
||||
|
||||
You can put any code as these lists, and you can move it to the return stack for execution using the word call. This technique is used very often for higher-order functions, largely the same way \texttt{[']} or \texttt{'} is used. \texttt{[ word ]} is the Factor equivalent of \texttt{['] word} for most purposes, but if you're going to be inspecting the word with operations like see, prefix it with a backslash (\texttt{\char'134 word}). One of the most visible differences between Factor and Forth is the tendency to use these code quotations where one would use immediate words in Forth.
|
||||
|
||||
Like many Forths, Factor uses a vocabulary system. Factor's vocabulary system revolves around two parsing words, \texttt{USE:} and \texttt{IN:}. \texttt{USE:} opens another vocabulary for use in the current one, and \texttt{IN:} changes the current vocabulary. But because of Factor's philosophy of constant testing, vocabularies have no privacy, unlike most Forth wordlist systems.
|
||||
|
||||
In place of variables that Forth uses, Factor has dynamic scoping. This makes it easier to isolate the side effects of a piece of code, but sometimes things might not work as expected when scopes are improperly used. The equivalent of the Forth code
|
||||
\begin{verbatim}
|
||||
variable x
|
||||
3 x !
|
||||
x @ .
|
||||
\end{verbatim}
|
||||
is
|
||||
\begin{verbatim}
|
||||
SYMBOL: x
|
||||
3 x set
|
||||
x get .
|
||||
\end{verbatim}
|
||||
The biggest difference there semantically is between \texttt{variable} and \texttt{SYMBOL:}. In Forth, when you make a variable, an actual place in memory is allocated. But in Factor, when you make a symbol using \texttt{SYMBOL:}, all you're doing is making a unique identifier. Technically, when you make a symbol, all you're doing is making a word that pushes itself. \verb|SYMBOL: x| is in that way equivalent to, in Forth, \verb|: x ['] x ;|, but in Factor it's much more useful. The variable system in Factor needs an identifier for each value, and a symbol serves this purpose. You could, if you wanted to, use any other type of data for the identifier for a variable, but it is not recommended. Factor lets you circumvent the local dynamic scopes and use global scope, if needed.
|
||||
|
||||
Cheat sheet:
|
||||
|
||||
\begin{tabular}{|l|p{3.5cm}|p{4cm}|} \hline
|
||||
Forth & Factor & Comments\\ \hline
|
||||
\texttt{+} & \texttt{+} & \emph{when applied on integers, it's the same}\\
|
||||
\texttt{-} & \texttt{-} & \emph{``''}\\
|
||||
\texttt{*} & \texttt{*} & \emph{``''}\\
|
||||
\texttt{/} & \texttt{/} & \emph{``''}\\
|
||||
\texttt{s" string"} & \texttt{"string"} & \emph{'\"' is still a word in Factor}\\
|
||||
\texttt{scan} & \texttt{scan-word} & \emph{Factor and Forth have really similar parsing systems}\\
|
||||
\texttt{execute} & \texttt{execute} &\\
|
||||
\texttt{,} or \texttt{compile} or \texttt{[compile]} & \texttt{swons} & \emph{swons is helping assemble the quotation, taking the parse tree from the stack}\\
|
||||
\texttt{:} & \texttt{:} & \emph{In Factor, redefinition affects prior uses of the word unless you FORGET: the word.}\\
|
||||
\texttt{;} & \texttt{;} & \emph{; is more general in Factor than Forth}\\
|
||||
\texttt{see word} & \texttt{\ word see} &\\
|
||||
\texttt{' word or ['] word} & \texttt{\char'134 word or [ word ]} &\\
|
||||
\texttt{if a else b then} & \texttt{[ a ] [ b ] ifte} &\\
|
||||
\texttt{if a then} & \texttt{[ a ] when} &\\
|
||||
\texttt{for a next} & \texttt{[ a ] repeat} or \texttt{[ a ] times}&\\ \hline
|
||||
\end{tabular}
|
||||
|
||||
\section{Joy}
|
||||
|
||||
Factor derives its code quotation system and combinators from Joy, and it shares concatenativity with Joy. But overall, Factor is much less pure than Joy. Factor has a much stronger emphasis on practicality than Joy, which is more theory-oriented. Factor has mutable datastructures, dynamic scope, and an extensible parser. Factor has doesn't have Joy's sets, but it has all of its other datastructures, and also vectors, hashtables, and tuples (user-defined structures). Factor provides much more reflection capabilities than Joy, and much of Factor is written in Factor.
|
||||
|
||||
A big difference between Factor and Joy is the way that Factor encourages you to factor your program into tiny pieces, like Forth. So some words that may have been considered good style in Joy can be considered horrible in Factor. The optimal Factor word contains 7 words. This stylistic difference makes Factor's library very different in order to encourage factoring. For most of Joy's recursive combinators, Factor just uses recursion. Factor does away with some of Joy's words like cond and case, which usually just lead to words that are too big.
|
||||
|
||||
Factor's datastructure library differs vastly from Joy's. Joy has 4 types: sets, lists, numbers and strings. Factor, on the other hand, has over 20 types, ranging from unsafe arrays to rational numbers to C pointers. Factor has all of Joy's datastructures except for sets. Factor also has user-defined datastructures called \emph{tuples}.
|
||||
|
||||
On a superficial analysis, the biggest difference between Factor's and Joy's syntaxes is the number of spaces used: Factor, unlike Joy, requires that you use spaces on either side of '[', ']', '{', and '}'. Another difference is the definition syntax. Joy provides many keywords for definition, the basic syntax being \verb|DEFINE x == y.|, whereas Factor uses just a few parsing words for definition: \verb|: x y ;|. But Factor has many semanically different forms of definition, such as defining a method and defining a symbol. These all use different parsing words, using Factor's extensible parser.
|
||||
|
||||
Cheat sheet:
|
||||
|
||||
\begin{tabular}{|l|lp{3.5cm}|lp{4cm}|} \hline
|
||||
Joy & Factor & Comments\\ \hline
|
||||
\texttt{+} & \texttt{+} &\\
|
||||
\texttt{-} & \texttt{-} &\\
|
||||
\texttt{*} & \texttt{*} &\\
|
||||
\texttt{/} & \texttt{/} &\\
|
||||
\texttt{cons} & \texttt{cons} & \emph{Only on lists for Factor}\\
|
||||
\texttt{uncons} & \texttt{uncons} & \emph{``''}\\
|
||||
\texttt{car} & \texttt{car} & \emph{``''}\\
|
||||
\texttt{cdr} & \texttt{cdr} & \emph{``''}\\
|
||||
\texttt{unswons} & \texttt{unswons} & \emph{``''}\\
|
||||
\texttt{swap} & \texttt{swap} &\\
|
||||
\texttt{dup} & \texttt{dup} &\\
|
||||
\texttt{pop} & \texttt{drop} &\\
|
||||
\texttt{[code] dip} & \texttt{>r code r>} &\\
|
||||
\texttt{[code or list]} & \texttt{[ code or list ]} &\\
|
||||
\texttt{times} & \texttt{times} &\\
|
||||
\texttt{"string"} & \texttt{"string"} &\\
|
||||
\texttt{DEFINE x == y.} & \texttt{: x y ;} & \emph{In Factor, words can be redefined}\\
|
||||
\texttt{rollup} & \texttt{-rot} &\\
|
||||
\texttt{rolldown} & \texttt{rot} &\\
|
||||
\texttt{[]} & \texttt{f} or \texttt{[ ]} &\\
|
||||
\texttt{false} & \texttt{f} or \texttt{[ ]} &\\
|
||||
\texttt{true} & \texttt{t} &\\
|
||||
\texttt{[a] [b] [c] ifte} & \texttt{a [ b ] [ c ] ifte} & \emph{Factor doesn't restore the stack}\\
|
||||
\texttt{step} & \texttt{each} & \emph{Only on lists in Factor}\\
|
||||
\texttt{map} & \texttt{map} & \emph{``'' and Factor doesn't restore the stack}\\
|
||||
\hline
|
||||
\end{tabular}
|
||||
|
||||
\section{Common Lisp and Scheme}
|
||||
|
||||
Common Lisp and Scheme don't have many similarities to Factor on the surface, but there are some concepts carried over from one to the other. One of Factor's biggest influences is Lisp.
|
||||
|
||||
Factor holds may similarites to CLOS. \texttt{TUPLE:} is vaguely analogous to defstruct, though it doesn't provide nearly as much flexibility. In Factor, you can define methods, but they can only be single-dispatch. In Factor, as in CLOS, generic functions/words must be explicitly declared before defining methods on them.
|
||||
|
||||
Factor's builtin datatypes are also similar to Lisp. Lists and vectors have correctly corresponding names and meanings in all three languages we're discussing, and so are hashtables between Common Lisp and Factor. Factor provides library functions for dealing with alists, though not plists.
|
||||
|
||||
Factor's \texttt{callcc0} and \texttt{callcc1} are essentially the same as Scheme's \texttt{call-with-current-continuation} (aka \texttt{call/cc}). The two versions in Factor exist because you need to explicitly specify the arity of your continuation, since factor has no variable argument mechanism. But usually in Factor, you would wrap up continuations in a library rather than use them directly. There is no equivalent of \texttt{dynamic-wind}, and instead, \texttt{catch} (the error handler) is used for most of those resource-handing places.
|
||||
|
||||
Though Factor's "macros" are actually extensions to the parser, similar to reader macros, certain things, such as the generic word system, are implemented like Common Lisp macros, generating a quote at parsetime and substituting it in. This is possible because Factor shares with Lisp and Scheme the principle that code is data, namely nested lists. Below is a list of analogous or equivalent things in Factor and Lisp.
|
||||
|
||||
Cheat sheet:
|
||||
|
||||
\begin{tabular}{|lp{2cm}|lp{2cm}|lp{2cm}|lp{2cm}|} \hline
|
||||
Common Lisp & Factor & Scheme & Comments
|
||||
\texttt{(defun a (b) c)} & \texttt{: a c ;} & \texttt{(define (a b) c)} & \emph{Passing around data is implicit; use the stack}\\
|
||||
\texttt{(defvar a b)} & \texttt{: a b ;} & \texttt{(define a b)} & \emph{Make sure B is some kind of mutable structure}\\
|
||||
\texttt{(defparameter a b)} & \texttt{SYMBOL: a b a set} & & \emph{New dynamic scopes are explicit}\\
|
||||
\texttt{\#'a} & \texttt{[ a ]} & \texttt{a} &\\
|
||||
\texttt{(lambda (a) b)} & \texttt{[ b ]} & \texttt{(lambda (a) b)} &\\
|
||||
\texttt{'(a b c)} & \texttt{[ a b c ]} & \texttt{'(a b c)} &\\
|
||||
\texttt{cons} & \texttt{cons} & \texttt{cons} &\\
|
||||
\texttt{car} & \texttt{car} & \texttt{car} & \emph{Factor's f car returns f, unlike Scheme}\\
|
||||
\texttt{cdr} & \texttt{cdr} & \texttt{cdr} & \emph{``''}\\
|
||||
\texttt{+} & \texttt{+} & \texttt{+} & \emph{Exactly two arguments in Factor}\\
|
||||
\texttt{(- x)} & \texttt{x neg} & \texttt{(- x)} &\\
|
||||
\texttt{(- a b)} & \texttt{a b -} & \texttt{(- a b)} & \emph{``''}\\
|
||||
\texttt{*} & \texttt{*} & \texttt{*} & \emph{``''}\\
|
||||
\texttt{/} & \texttt{/} & \texttt{/} & \emph{``''}\\
|
||||
\texttt{(funcall x y)} & \texttt{y x call} & \texttt{(x y)} &\\
|
||||
\texttt{truncate} & \texttt{/mod} & \emph{This is truncate with 2 args using both values. Only on ints}\\
|
||||
& \texttt{callcc0} & \texttt{call/cc} & \emph{When the continuation is used with no args}\\
|
||||
& \texttt{callcc1} & \texttt{call/cc} & \emph{When the continuation is used with one arg}\\
|
||||
\texttt{"string"} & \texttt{"string"} & \texttt{"string"} &\\
|
||||
\texttt{(defstruct name stuff)} & \texttt{TUPLE: name stuff ;} & &\\
|
||||
\texttt{(defmacro a blah)} & \texttt{: a blah ; parsing} & \texttt{(define-syntax a blah)} & \emph{The macro systems are completely different}\\
|
||||
\texttt{(loop for a in b do c)} & \texttt{b [ c ] each} & \texttt{(for-each (lambda (a) c) b)} &\\
|
||||
\texttt{(loop for a in b collect c)} & \texttt{b [ c ] map} & \texttt{(map (lambda (a) c) b)} &\\
|
||||
\hline
|
||||
\end{tabular}
|
||||
|
||||
\section{Python}
|
||||
|
||||
Although Python and Factor aren't the most similar languages, you can still see many similarities through them. Python has some similarities to Common Lisp, and Common Lisp to Factor, so by that proxy, Python has some similarities to Factor. Still, a knowledge of Python can help you in learning Factor.
|
||||
|
||||
There's one thing that Python does similarly to Factor seperating them from other languages: privacy. Neither Factor nor Python have any sort of privacy. We're all adults, aren't we? Well, except for the person writing this :). Anyway, Python and Factor both don't have privacy in their module systems or object systems. Another similarity in the module systems is the tendency to require them to be imported for many basic tasks. Factor takes this even further than Python, so far that you can't really do anything without opening a module; it's not even Turing-complete! Factor's modules, called vocabularies, don't have the option of using hierarchical naming. The equivalent of \verb|from module import *| is \verb|USE: module|. If you want to import a bunch of modules, there's a shortcut syntax: \verb|USING: mod1 mod2 mod3 ;| imports everything from mod1, mod2, and mod3. Don't worry about the apparent lack of first-class modules; it's possible to access vocabularies, stored as hashtables, in the vocabulary variable.
|
||||
|
||||
Factor's syntax and semantics look so extremely unlike Python, it's hard to believe that they're related at all. Take a simple function to square a number, written using multiplication: In Python, it's
|
||||
\begin{verbatim}
|
||||
def square(x):
|
||||
return x*x
|
||||
\end{verbatim}
|
||||
and then look at Factor's: \verb|: square dup * ;| The main reason for this difference is that Python is \emph{applicative} while Factor is \emph{concatenative}. For all intents and purposes, that means that Factor stores data on a \emph{stack} and Python stores data in variables. When calling \texttt{square} in Factor, first \texttt{dup} duplicates the first item on the stack and then \texttt{*} multiplies the top two items on the stack. Don't worry if you don't understand it; I'm not really explaining it very well. Just read the Factor Developer Guide.
|
||||
|
||||
For many things, such as iterating through a list, Python uses a builtin syntax while Factor uses a word (the equivalent of a function) defined in a library. These words take what's called a code quotation, the rough equivalent of a lambda, as an argument. Imagine if, in Python for conditionals, you wrote
|
||||
\begin{verbatim}
|
||||
if x: y
|
||||
else: z
|
||||
\end{verbatim}
|
||||
as \verb|if(x, lambda: y, lambda: z)|. This is essentially what Factor does, in the syntax \verb|x [ y ] [ z ] ifte|. Words like ifte are used for everything from the equivalents of \verb|[x+1 for x in list]| to
|
||||
\begin{verbatim}
|
||||
while x==y:
|
||||
do(something)
|
||||
\end{verbatim}
|
||||
|
||||
As I mentioned earlier, Factor has an object system, and like Python's, it has no privacy. But beyond that, there's no resemblance. I'll show you a Python class and its equivalent in Factor:
|
||||
\begin{verbatim}
|
||||
class Something(object):
|
||||
def __init__(self, x, y, z):
|
||||
self.x = x
|
||||
self.y = y
|
||||
self.z = z
|
||||
return self
|
||||
def amethod(self):
|
||||
result = self.x+self.y+self.z
|
||||
return result
|
||||
\end{verbatim}
|
||||
The Factor equivalent looks nothing like it. This requires that the generic function \texttt{amethod} already exist.
|
||||
\begin{verbatim}
|
||||
TUPLE: something x y z ;
|
||||
M: something amethod
|
||||
dup dup something-x -rot something-y swap something-z + + ;
|
||||
\end{verbatim}
|
||||
Factor, like Python, has a small but still existent difference between types and classes on approximately the same lines. Factor's object system is written completely within Factor, but the types are hard-coded in.
|
||||
|
||||
Factor has no direct equivalent of Python's lists, but instead it has several other collection types for different purposes. Factor has something called lists, but don't confuse them with Python's lists: Factor lists are linked lists, aka cons cells. These linked lists are immutable. The syntax for creating the equivalent of \verb|[1, 2, 3]| as a linked list in Factor is \verb|[ 1 2 3 ]|. Notice where spaces are: you can't remove any of those. Additionally, you can't put arbitrary expressions in this form; you must use literals. To use arbitrary expressions, you use the \texttt{makelist} combinator. The equivalent of \verb|[1+2, 3+4]| is \verb|[ 1 2 + , 3 4 + , ] make-list|. Notice how you have to put a comma after the last item, not just between items. Another collection type in Factor is the vector. Vectors are used when you want to index it with a number. The syntax is similar to lists: \verb|{ 1 2 3 }| is like \verb|[1, 2, 3]|. There is no equivalent of make-list for vectors. Vectors are fixed-length but they are mutable. Factor has hashtables in place of Pythons's dictionaries. \verb|{"hi": 1, "hello": 2}| is \verb|{{ [[ "hi" 1 ]] [[ "hello" 2 ]] }}|.
|
||||
|
||||
Cheat sheet:
|
||||
|
||||
\begin{tabular}{|l|lp{3.5cm}|lp{4cm}|} \hline
|
||||
Python & Factor & Comments\\ \hline
|
||||
%\begin{verbatim}
|
||||
%def function(argument):
|
||||
% """Docstring"""
|
||||
% code
|
||||
%\end{verbatim}
|
||||
%&
|
||||
%\begin{verbatim}
|
||||
%: function
|
||||
% #! Docstring
|
||||
% code ;
|
||||
%\end{verbatim}
|
||||
%& emph{Passing arguments is implicit on the stack}\\
|
||||
\texttt{a+b} & \texttt{a b +} &\\
|
||||
\texttt{a-b} & \texttt{a b -} &\\
|
||||
\texttt{a*b} & \texttt{a b *} &\\
|
||||
\texttt{a/b} & \texttt{a b /} & \emph{Factor has support for rational numbers}\\
|
||||
\verb|a**b| & \texttt{a b \^} & \\
|
||||
%\begin{verbatim}
|
||||
%for item in list:
|
||||
% code
|
||||
%\end{verbatim}
|
||||
%& \texttt{list [ code ] each} & \emph{Only for linked lists in Factor. Different words for different collections}\\
|
||||
\texttt{[something for item in list]} & \texttt{list [ something ] map} & \emph{Only for linked lists in Factor. Different words for different collections}\\
|
||||
\texttt{[item for item in list if test]} & \texttt{list [ test ] filter} & \emph{``''}
|
||||
\texttt{\#} \emph{comment} & \texttt{! } \emph{comment} &\\
|
||||
\texttt{lambda arg: value} & \texttt{[ value ]} &\\
|
||||
\texttt{"string"} or \texttt{'string'} & \texttt{"string"} &\\
|
||||
\hline
|
||||
\end{tabular}
|
||||
|
||||
\end{document}
|
|
@ -0,0 +1,396 @@
|
|||
%%
|
||||
%% This is file `glossary.sty',
|
||||
%% generated with the docstrip utility.
|
||||
%%
|
||||
%% The original source files were:
|
||||
%%
|
||||
%% glossary.dtx (with options: `package')
|
||||
%% Copyright (C) 2000 Nicola Talbot, all rights reserved.
|
||||
%% If you modify this file, you must change its name first.
|
||||
%% You are NOT ALLOWED to distribute this file alone. You are NOT
|
||||
%% ALLOWED to take money for the distribution or use of either this
|
||||
%% file or a changed version, except for a nominal charge for copying
|
||||
%% etc.
|
||||
\NeedsTeXFormat{LaTeX2e}
|
||||
\ProvidesPackage{glossary}
|
||||
\RequirePackage{ifthen}
|
||||
\RequirePackage{keyval}
|
||||
\define@key{gloss}
|
||||
{style}
|
||||
{\ifthenelse{\equal{#1}{list} \or \equal{#1}{altlist} \or \equal{#1}{super} \or \equal{#1}{long}}
|
||||
{\def\gls@style{#1}}
|
||||
{\PackageError{glossary}
|
||||
{Unknown glossary style '#1'}
|
||||
{Available styles are: list, altlist, super and long}}}
|
||||
|
||||
\define@key{gloss}
|
||||
{header}[plain]{\ifthenelse{\equal{#1}{none} \or \equal{#1}{plain}}
|
||||
{\def\gls@header{#1}}
|
||||
{\PackageError{glossary}
|
||||
{Unknown glossary style '#1'}
|
||||
{Available styles are: none and plain}}}
|
||||
|
||||
\define@key{gloss}
|
||||
{border}[plain]{\ifthenelse{\equal{#1}{none} \or \equal{#1}{plain}}
|
||||
{\def\gls@border{#1}}
|
||||
{\PackageError{glossary}
|
||||
{Unknown glossary border '#1'}
|
||||
{Available styles are: none and plain}}}
|
||||
\newcount\gls@cols
|
||||
\define@key{gloss}{cols}{\gls@cols=#1\relax
|
||||
\ifthenelse{\gls@cols<2 \or \gls@cols>3}
|
||||
{\PackageError{glossary}
|
||||
{invalid number of columns}
|
||||
{The cols option can only be 2 or 3}}
|
||||
{}}
|
||||
|
||||
\define@key{gloss}
|
||||
{number}
|
||||
{\ifthenelse{\equal{#1}{none}\or\equal{#1}{page}\or\equal{#1}{section}}
|
||||
{\def\gls@number{#1}}
|
||||
{\PackageError{glossary}
|
||||
{Unknown glossary number style '#1'}
|
||||
{Available styles are: none, page and section}}}
|
||||
|
||||
\newif\ifgls@toc
|
||||
\define@key{gloss}{toc}[true]{\ifthenelse{\equal{#1}{true} \or \equal{#1}{false}}
|
||||
{\csname gls@toc#1\endcsname}
|
||||
{\PackageError{glossary}{Glossary option 'toc' is boolean}
|
||||
{The value of 'toc' can only be set to 'true' or 'false'}}}
|
||||
|
||||
\newif\ifglshyper
|
||||
\define@key{gloss}{hyper}[true]{\ifthenelse{\equal{#1}{true} \or \equal{#1}{false}}
|
||||
{\csname glshyper#1\endcsname}
|
||||
{\PackageError{glossary}{Glossary option 'hyper' is boolean}
|
||||
{The value of 'hyper' can only be set to 'true' or 'false'}}}
|
||||
\def\gls@style{long}
|
||||
\def\gls@header{none}
|
||||
\def\gls@border{none}
|
||||
\def\gls@number{page}
|
||||
\gls@cols=2\relax
|
||||
\gls@tocfalse
|
||||
\@ifundefined{hyperpage}{\glshyperfalse}{\glshypertrue}
|
||||
|
||||
\DeclareOption*{\edef\@pkg@ptions{\noexpand\setkeys{gloss}{\CurrentOption}}
|
||||
\ifthenelse{\equal{\CurrentOption}{}}{}{\@pkg@ptions}}
|
||||
|
||||
\ProcessOptions
|
||||
\ifthenelse{\(\equal{\gls@style}{list} \or \equal{\gls@style}{altlist}\) \and \(\not\equal{\gls@header}{none} \or \not\equal{\gls@border}{none} \or \gls@cols=3\)}
|
||||
{\PackageError{glossary}{You can't have option 'style=list' or 'style=altlist' in combination with any of the other options}
|
||||
{The 'list' and 'altlist' options don't have a header, border or number of columns option.}}
|
||||
{}
|
||||
\define@key{wrgloss}{name}{\def\@n@me{#1}}
|
||||
\define@key{wrgloss}{description}{\def\@descr{#1}}
|
||||
\define@key{wrgloss}{sort}{\def\@s@rt{#1}}
|
||||
\define@key{wrgloss}{format}{\def\@f@rm@t{#1}}
|
||||
\renewcommand{\@wrglossary}[1]{\relax
|
||||
\def\@n@me{}\def\@descr{}\def\@s@rt{}\def\@f@rm@t{}\relax
|
||||
\setkeys{wrgloss}{#1}\relax
|
||||
\ifthenelse{\equal{\@s@rt}{}}
|
||||
{\relax
|
||||
\ifthenelse{\equal{\@f@rm@t}{}}
|
||||
{\protected@write\@glossaryfile{}{\string\glossaryentry{\@n@me @{\@n@me}\@descr\string\relax|glsnumformat}{\theglossarynum}}}
|
||||
{\protected@write\@glossaryfile{}{\string\glossaryentry{\@n@me @{\@n@me}\@descr\string\relax|\@f@rm@t}{\theglossarynum}}}\relax
|
||||
}{\relax
|
||||
\ifthenelse{\equal{\@f@rm@t}{}}
|
||||
{\protected@write\@glossaryfile{}{\string\glossaryentry{\@s@rt @{\@n@me}\@descr\string\relax|glsnumformat}{\theglossarynum}}}
|
||||
{\protected@write\@glossaryfile{}{\string\glossaryentry{\@s@rt @{\@n@me}\@descr\string\relax|\@f@rm@t}{\theglossarynum}}}\relax
|
||||
}\relax
|
||||
\endgroup\@esphack
|
||||
}
|
||||
\ifthenelse{\equal{\gls@number}{page}}{
|
||||
\newcommand{\theglossarynum}{\thepage}
|
||||
\newcommand{\pagecompositor}{-}
|
||||
\newcommand{\delimN}{, }
|
||||
\newcommand{\delimR}{--}
|
||||
\ifglshyper\newcommand{\glsnumformat}[1]{\hyperpage{#1}}\else\newcommand{\glsnumformat}[1]{#1}\fi}
|
||||
{\ifthenelse{\equal{\gls@number}{section}}
|
||||
{\newcommand{\theglossarynum}{\thesection}
|
||||
\newcommand{\pagecompositor}{.}
|
||||
\newcommand{\delimN}{, }
|
||||
\newcommand{\delimR}{--}
|
||||
\ifglshyper\newcommand{\glsnumformat}[1]{\hypersection{#1}}\else\newcommand{\glsnumformat}[1]{#1}\fi}
|
||||
{\newcommand{\theglossarynum}{\thepage}
|
||||
\newcommand{\pagecompositor}{-}
|
||||
\newcommand{\delimN}{}
|
||||
\newcommand{\delimR}{}
|
||||
\newcommand{\glsnumformat}[1]{}}}
|
||||
\newcommand\printglossary{\@input@{\jobname.gls}}
|
||||
\newcommand{\glossaryname}{Glossary}
|
||||
\newcommand{\entryname}{Notation}
|
||||
\newcommand{\descriptionname}{Description}
|
||||
\newcommand{\istfilename}{\jobname.ist}
|
||||
\newenvironment{theglossary}
|
||||
{\@ifundefined{chapter}
|
||||
{\section*{\glossaryname}\ifgls@toc\addcontentsline{toc}{section}{\glossaryname}\fi}
|
||||
{\chapter*{\glossaryname}\ifgls@toc\addcontentsline{toc}{chapter}{\glossaryname}\fi}
|
||||
\glossarypreamble\@bef@reglos}
|
||||
{\@ftergl@s\glossarypostamble}
|
||||
|
||||
\newcommand{\glossarypreamble}{}
|
||||
\newcommand{\glossarypostamble}{}
|
||||
|
||||
\newif\ifgloitemfirst
|
||||
\newcommand{\@bef@reglos}{\global\gloitemfirsttrue\beforeglossary}
|
||||
\newcommand{\@ftergl@s}{\afterglossary\global\gloitemfirstfalse}
|
||||
|
||||
\ifthenelse{\equal{\gls@style}{list} \or \equal{\gls@style}{altlist}}
|
||||
{
|
||||
\newcommand{\beforeglossary}{\begin{description}}
|
||||
\newcommand{\afterglossary}{\end{description}}
|
||||
\newcommand{\gloskip}{\indexspace}
|
||||
\ifthenelse{\equal{\gls@style}{list}}
|
||||
{\newcommand{\gloitem}[1]{\item[#1]}
|
||||
\newcommand{\glodelim}{, }}
|
||||
{\newcommand{\gloitem}[1]{\item[#1]\mbox{}\par}
|
||||
\newcommand{\glodelim}{ }}
|
||||
}{
|
||||
\ifthenelse{\equal{\gls@style}{super}}{
|
||||
\IfFileExists{supertab.sty}{\RequirePackage{supertab}}
|
||||
{\IfFileExists{supertabular.sty}{\RequirePackage{supertabular}}
|
||||
{\PackageError{glossary}{Option "super" chosen, but can't find "supertab" package}
|
||||
{If you want the "super" option, you have to have the "supertab" package installed.}}}
|
||||
}
|
||||
{\RequirePackage{longtable}}
|
||||
|
||||
\newlength{\descriptionwidth}
|
||||
\setlength{\descriptionwidth}{0.6\textwidth}
|
||||
|
||||
\ifthenelse{\equal{\gls@header}{none}}
|
||||
{
|
||||
\ifthenelse{\equal{\gls@border}{none}}
|
||||
{\newcommand{\glossaryheader}{}}
|
||||
{\newcommand{\glossaryheader}{\hline }}
|
||||
}
|
||||
{
|
||||
\ifnum\gls@cols=2\relax
|
||||
\ifthenelse{\equal{\gls@border}{none}}
|
||||
{\newcommand{\glossaryheader}
|
||||
{\bfseries\entryname & \bfseries \descriptionname\\}}
|
||||
{\newcommand{\glossaryheader}
|
||||
{\hline\bfseries\entryname & \bfseries\descriptionname
|
||||
\\\hline\hline}}
|
||||
\else
|
||||
\ifthenelse{\equal{\gls@border}{none}}
|
||||
{\newcommand{\glossaryheader}
|
||||
{\bfseries\entryname & \bfseries \descriptionname & \\}}
|
||||
{\newcommand{\glossaryheader}
|
||||
{\hline\bfseries\entryname &\bfseries\descriptionname &
|
||||
\\\hline\hline}}
|
||||
\fi
|
||||
}
|
||||
|
||||
\ifthenelse{\equal{\gls@border}{none}}
|
||||
{
|
||||
\ifnum\gls@cols=2\relax
|
||||
\@ifundefined{newcolumntype}{\newcommand{\glossaryalignment}{@{\hspace{\tabcolsep}\bfseries}lp{\descriptionwidth}}}{
|
||||
\newcolumntype{G}{@{\hspace{\tabcolsep}\bfseries}lp{\descriptionwidth}}}
|
||||
\else
|
||||
\@ifundefined{newcolumntype}{\newcommand{\glossaryalignment}{@{\hspace{\tabcolsep}\bfseries}lp{\descriptionwidth}l}}{
|
||||
\newcolumntype{G}{@{\hspace{\tabcolsep}\bfseries}lp{\descriptionwidth}l}}
|
||||
\fi
|
||||
|
||||
\ifthenelse{\equal{\gls@style}{super}}{
|
||||
\newcommand{\afterglossary}{ \\\end{supertabular}}
|
||||
}
|
||||
{
|
||||
\newcommand{\afterglossary}{ \\\end{longtable}}
|
||||
}
|
||||
|
||||
\newcommand{\glosstail}{}
|
||||
}
|
||||
{
|
||||
\ifnum\gls@cols=2\relax
|
||||
\@ifundefined{newcolumntype}{\newcommand{\glossaryalignment}{|@{\hspace{\tabcolsep}\bfseries}lp{\descriptionwidth}|}}{
|
||||
\newcolumntype{G}{|@{\hspace{\tabcolsep}\bfseries}lp{\descriptionwidth}|}}
|
||||
\else
|
||||
\@ifundefined{newcolumntype}{\newcommand{\glossaryalignment}{|@{\hspace{\tabcolsep}\bfseries}lp{\descriptionwidth}l|}}{
|
||||
\newcolumntype{G}{|@{\hspace{\tabcolsep}\bfseries}lp{\descriptionwidth}l|}}
|
||||
\fi
|
||||
|
||||
\ifthenelse{\equal{\gls@style}{super}}{
|
||||
\newcommand{\afterglossary}{ \\\hline\end{supertabular}}
|
||||
}
|
||||
{
|
||||
\newcommand{\afterglossary}{ \\\hline\end{longtable}}
|
||||
}
|
||||
|
||||
\newcommand{\glosstail}{\hline}
|
||||
}
|
||||
|
||||
\ifthenelse{\equal{\gls@style}{super}}
|
||||
{
|
||||
\@ifundefined{newcolumntype}{
|
||||
\newcommand{\beforeglossary}
|
||||
{\tablehead{\glossaryheader}\tabletail{\glosstail}
|
||||
\begin{supertabular}{\glossaryalignment}}}
|
||||
{\newcommand{\beforeglossary}
|
||||
{\tablehead{\glossaryheader}\tabletail{\glosstail}
|
||||
\begin{supertabular}{G}}}
|
||||
}
|
||||
{
|
||||
\@ifundefined{newcolumntype}{\newcommand{\beforeglossary}
|
||||
{\begin{longtable}{\glossaryalignment}
|
||||
\glossaryheader\endhead\glosstail\endfoot}}
|
||||
{\newcommand{\beforeglossary}
|
||||
{\begin{longtable}{G}
|
||||
\glossaryheader\endhead\glosstail\endfoot}}
|
||||
}
|
||||
|
||||
\ifnum\gls@cols=2\relax
|
||||
\newcommand{\gloskip}{\ifgloitemfirst\global\gloitemfirstfalse \else\\ \fi &}
|
||||
\newcommand{\glodelim}{, }
|
||||
\else
|
||||
\newcommand{\gloskip}{\ifgloitemfirst\global\gloitemfirstfalse \else\\ \fi & &}
|
||||
\newcommand{\glodelim}{& }
|
||||
\fi
|
||||
\newcommand{\gloitem}[1]{\ifgloitemfirst\global\gloitemfirstfalse #1 \else \\#1 \fi &}
|
||||
}
|
||||
|
||||
\ifthenelse{\equal{\gls@number}{none} \and \gls@cols<3}{\renewcommand{\glodelim}{}}{}
|
||||
\newif\ifist
|
||||
\let\noist=\istfalse
|
||||
\if@filesw\isttrue\else\istfalse\fi
|
||||
|
||||
\newwrite\istfile
|
||||
\catcode`\%11\relax
|
||||
\newcommand{\writeist}{
|
||||
\openout\istfile=\istfilename
|
||||
\write\istfile{% makeindex style file created by LaTeX for document "\jobname" on \the\year-\the\month-\the\day}
|
||||
\write\istfile{keyword "\string\\glossaryentry"}
|
||||
\write\istfile{preamble "\string\\begin{theglossary}"}
|
||||
\write\istfile{postamble "\string\n\string\\end{theglossary}\string\n"}
|
||||
\write\istfile{group_skip "\string\\gloskip "}
|
||||
\write\istfile{item_0 "\string\n\string\\gloitem "}
|
||||
\write\istfile{delim_0 "\string\n\string\\glodelim "}
|
||||
\write\istfile{page_compositor "\pagecompositor"}
|
||||
\write\istfile{delim_n "\string\\delimN"}
|
||||
\write\istfile{delim_r "\string\\delimR"}
|
||||
\closeout\istfile
|
||||
}
|
||||
\catcode`\%14\relax
|
||||
\renewcommand{\makeglossary}{
|
||||
\newwrite\@glossaryfile
|
||||
\immediate\openout\@glossaryfile=\jobname.glo
|
||||
\def\glossary{\@bsphack \begingroup \@sanitize \@wrglossary }
|
||||
\typeout {Writing glossary file \jobname .glo }
|
||||
\let \makeglossary \@empty
|
||||
\ifist\writeist\fi
|
||||
\noist}
|
||||
\newcommand{\newglossarytype}[3]{
|
||||
\@ifundefined{#1}{%
|
||||
\def\@glstype{#1}\def\@glsout{#2}\def\@glsin{#3}%
|
||||
\expandafter\edef\csname make\@glstype\endcsname{\noexpand\@m@kegl@ss{\@glstype}{\@glsout}}
|
||||
\expandafter\edef\csname \@glstype\endcsname{\noexpand\@gl@ss@ary{\@glstype}}
|
||||
\expandafter\edef\csname print\@glstype\endcsname{\noexpand\@prntgl@ss@ry{\@glsin}}
|
||||
}{\PackageError{glossary}{Command \expandafter\string\csname #1\endcsname \space already defined}{%
|
||||
You can't call your new glossary type '#1' because there already exists a command with this name}}
|
||||
}
|
||||
\newcommand\@m@kegl@ss[2]{
|
||||
\expandafter\newwrite\csname @#1file\endcsname
|
||||
\expandafter\immediate\expandafter\openout\csname @#1file\endcsname=\jobname.#2
|
||||
\typeout {Writing #1 file \jobname .#2 }
|
||||
\expandafter\let \csname make#1\endcsname \@empty
|
||||
\ifist\writeist\fi
|
||||
\expandafter\def\csname the#1num\endcsname{\thepage}
|
||||
\noist
|
||||
}
|
||||
\newcommand{\@wrgl@ss@ry}[2]{\relax
|
||||
\def\@n@me{}\def\@descr{}\def\@s@rt{}\def\@f@rm@t{}\relax
|
||||
\setkeys{wrgloss}{#2}\relax
|
||||
\ifthenelse{\equal{\@s@rt}{}}
|
||||
{\relax
|
||||
\ifthenelse{\equal{\@f@rm@t}{}}
|
||||
{\expandafter\protected@write\csname @#1file\endcsname{}{\string\glossaryentry{\@n@me @{\@n@me}\@descr\string\relax|glsnumformat}{\csname the#1num\endcsname}}}
|
||||
{\expandafter\protected@write\csname @#1file\endcsname{}{\string\glossaryentry{\@n@me @{\@n@me}\@descr\string\relax|\@f@rm@t}{\csname the#1num\endcsname}}}\relax
|
||||
}{\relax
|
||||
\ifthenelse{\equal{\@f@rm@t}{}}
|
||||
{\expandafter\protected@write\csname @#1file\endcsname{}{\string\glossaryentry{\@s@rt @{\@n@me}\@descr\string\relax|glsnumformat}{\csname the#1num\endcsname}}}
|
||||
{\expandafter\protected@write\csname @#1file\endcsname{}{\string\glossaryentry{\@s@rt @{\@n@me}\@descr\string\relax|\@f@rm@t}{\csname the#1num\endcsname}}}\relax
|
||||
}\relax
|
||||
\endgroup\@esphack
|
||||
}
|
||||
\newcommand\@gl@ss@ary[1]{\@ifundefined{@#1file}{\@bsphack\begingroup \@sanitize \@index}{\@bsphack \begingroup \@sanitize \@wrgl@ss@ry{#1}}}
|
||||
\newcommand\@prntgl@ss@ry[1]{\@input@{\jobname.#1}}
|
||||
\@onlypreamble{\newglossarytype}
|
||||
\newcommand\@acrnmsh{}
|
||||
\newcommand\@acrnmln{}
|
||||
\newcommand\@acrnmcmd{}
|
||||
\newcommand\@acrnmgls{}
|
||||
\newcommand\@acrnmins{}
|
||||
|
||||
\newcommand{\glsprimaryfmt}[1]{\textbf{\glsnumformat{#1}}}
|
||||
|
||||
\newcommand{\newacronym}[4][]{%
|
||||
\ifthenelse{\equal{#1}{}}{\renewcommand\@acrnmcmd{#2}}{\renewcommand\@acrnmcmd{#1}}
|
||||
\@ifundefined{\@acrnmcmd}{%
|
||||
\renewcommand\@acrnmsh{#2}
|
||||
\renewcommand\@acrnmln{#3}
|
||||
\expandafter\gdef\csname @\@acrnmcmd @glsentryi\endcsname{{name={#3 (#2)},format=glsprimaryfmt,#4}}%
|
||||
\expandafter\gdef\csname @\@acrnmcmd @glsentry\endcsname{{name={#3 (#2)},format=glsnumformat,#4}}%
|
||||
\newboolean{\@acrnmcmd first}\setboolean{\@acrnmcmd first}{true}%
|
||||
\expandafter\edef\csname @\@acrnmcmd\endcsname{\noexpand\ifthenelse{\noexpand\boolean{\@acrnmcmd first}}%
|
||||
{\@acrnmln\noexpand\@acrnmins\ (\@acrnmsh)\noexpand\expandafter\noexpand\glossary\expandafter\noexpand\csname @\@acrnmcmd @glsentryi\endcsname%
|
||||
\noexpand\global\noexpand\let\expandafter\noexpand\csname if\@acrnmcmd first\endcsname=\noexpand\iffalse
|
||||
}%
|
||||
{\@acrnmsh\noexpand\@acrnmins\noexpand\expandafter\noexpand\glossary\expandafter\noexpand\csname @\@acrnmcmd @glsentry\endcsname}}
|
||||
\expandafter\edef\csname @s@\@acrnmcmd\endcsname{\noexpand\ifthenelse{\noexpand\boolean{\@acrnmcmd first}}%
|
||||
{\noexpand\MakeUppercase\@acrnmln\noexpand\@acrnmins\ (\@acrnmsh)\noexpand\expandafter\noexpand\glossary\expandafter\noexpand\csname @\@acrnmcmd @glsentryi\endcsname%
|
||||
\noexpand\global\noexpand\let\expandafter\noexpand\csname if\@acrnmcmd first\endcsname=\noexpand\iffalse
|
||||
}%
|
||||
{\noexpand\MakeUppercase\@acrnmsh\noexpand\@acrnmins\noexpand\expandafter\noexpand\glossary\expandafter\noexpand\csname @\@acrnmcmd @glsentry\endcsname}}
|
||||
\expandafter\edef\csname\@acrnmcmd\endcsname{\noexpand\@ifstar\expandafter\noexpand\csname @s@\@acrnmcmd\endcsname
|
||||
\expandafter\noexpand\csname @\@acrnmcmd\endcsname}%
|
||||
}
|
||||
{\PackageError{glossary}{Command '\expandafter\string\csname\@acrnmcmd\endcsname' already defined}{
|
||||
The command name specified by \string\newacronym already exists.}}}
|
||||
|
||||
\newcommand{\useacronym}{\@ifstar\@suseacronym\@useacronym}
|
||||
\newcommand{\@suseacronym}[2][]{{\def\@acrnmins{#1}\csname @s@#2\endcsname}}
|
||||
\newcommand{\@useacronym}[2][]{{\def\@acrnmins{#1}\csname @#2\endcsname}}
|
||||
\ifglshyper
|
||||
\def\hypersection#1{\@hypersection#1----\\}
|
||||
\def\@hypersection#1--#2--#3\\{%
|
||||
\ifx\\#2\\%
|
||||
\@commahypersection{#1}%
|
||||
\else
|
||||
\@ifundefined{hyperlink}{#1--#2}{\hyperlink{section.#1}{#1}--\hyperlink{section.#2}{#2}}%
|
||||
\fi
|
||||
}
|
||||
\def\@commahypersection#1{\@@commahypersection#1, ,\\}
|
||||
\def\@@commahypersection#1, #2,#3\\{%
|
||||
\ifx\\#2\\%
|
||||
\@ifundefined{hyperlink}{#1}{\hyperlink{section.#1}{#1}}%
|
||||
\else
|
||||
\@ifundefined{hyperlink}{#1, #2}{\hyperlink{section.#1}{#1}, \hyperlink{section.#2}{#2}}%
|
||||
\fi
|
||||
}
|
||||
|
||||
\ifthenelse{\equal{\gls@number}{section}}{
|
||||
\ifglshyper
|
||||
\@ifundefined{chapter}
|
||||
{}
|
||||
{\let\@gls@old@chapter\@chapter
|
||||
\def\@chapter[#1]#2{\@gls@old@chapter[{#1}]{#2}\@ifundefined{hyperdef}{}{\hyperdef{section}{\thechapter.0}{}}}}
|
||||
\fi
|
||||
|
||||
\providecommand\hypersf[1]{\textsf{\hypersection{#1}}}
|
||||
\providecommand\hypertt[1]{\texttt{\hypersection{#1}}}
|
||||
\providecommand\hyperbf[1]{\textbf{\hypersection{#1}}}
|
||||
\providecommand\hyperit[1]{\textit{\hypersection{#1}}}
|
||||
}
|
||||
{
|
||||
\providecommand\hypersf[1]{\textsf{\hyperpage{#1}}}
|
||||
\providecommand\hypertt[1]{\texttt{\hyperpage{#1}}}
|
||||
\providecommand\hyperbf[1]{\textbf{\hyperpage{#1}}}
|
||||
\providecommand\hyperit[1]{\textit{\hyperpage{#1}}}
|
||||
}
|
||||
\else
|
||||
\providecommand\hypersf[1]{\textsf{#1}}
|
||||
\providecommand\hypertt[1]{\texttt{#1}}
|
||||
\providecommand\hyperbf[1]{\textbf{#1}}
|
||||
\providecommand\hyperit[1]{\textit{#1}}
|
||||
\fi
|
||||
\endinput
|
||||
%%
|
||||
%% End of file `glossary.sty'.
|
123
doc/handbook.tex
123
doc/handbook.tex
|
@ -519,9 +519,10 @@ Reads the next word from the input string and appends the word to the parse tree
|
|||
|
||||
\subsubsection{Mutable literals}
|
||||
|
||||
\newcommand{\mutableglos}{\glossary{
|
||||
name=mutable object,
|
||||
description={an object whose slot values can be modified, or by transitivity, an object that refers to a mutable object via one of its slots}}}
|
||||
\newcommand{\mutableglos}{\glossary{name=mutable object,
|
||||
description=an object whose slot values can be changed}
|
||||
\glossary{name=immutable object,
|
||||
description=an object whose slot values cannot be changed}}
|
||||
\mutableglos
|
||||
|
||||
Using mutable object literals in word definitions requires care, since if those objects
|
||||
|
@ -986,8 +987,8 @@ description=a word that adds definitions to the dictionary}
|
|||
description=the collection of vocabularies making up the code in the Factor image}
|
||||
Words are the fundamental unit of code in Factor, analogous to functions or procedures in other languages. Words are also objects, and this concept forms the basis for Factor's meta-programming facilities. Words hold two distinct pieces of information:
|
||||
\begin{itemize}
|
||||
\item The word definition that determines what action is taken when the word is executed,
|
||||
\item A set of word properties, including the name of the word, the vocabulary it belongs do, documentation strings, and other meta-data.
|
||||
\item A definition, specifying the behavior of the word when executed,
|
||||
\item A set of word properties, including the name of the word, its vocabulary, any documentation strings, and other meta-data.
|
||||
\end{itemize}
|
||||
\wordtable{
|
||||
\ordinaryword{word?}{word?~( object -- ?~)}{words}
|
||||
|
@ -1025,7 +1026,7 @@ The \texttt{vocabs} parameter is a list of vocabulary names. If a word with the
|
|||
}
|
||||
Creates a new word \texttt{name} in \texttt{vocabulary}. If the vocabulary already contains a word with this name, the existing word is returned.
|
||||
\wordtable{
|
||||
\ordinaryword{create-in}{create ( name -- word )}{words}
|
||||
\ordinaryword{create-in}{create-in ( name -- word )}{words}
|
||||
}
|
||||
Creates a new word \texttt{name} in the current vocabulary. Should only be called from parsing words (\ref{parsing-words}), and in fact is defined as:
|
||||
\begin{verbatim}
|
||||
|
@ -1158,7 +1159,9 @@ description={a name/value pair stored in a word's properties}}
|
|||
\glossary{name=word properties,
|
||||
description={a hashtable associated with each word storing various sundry properties}}
|
||||
|
||||
Each word has an associated hashtable of properties. A common idiom in the Factor library is to use symbols for their properties. Conventionally, the property names are strings, but nothing requires that this be so.
|
||||
Each word has an associated hashtable of properties. Conventionally, the property names are strings, but nothing requires that this be so.
|
||||
|
||||
A common idiom in the Factor library is to use symbols for their properties.
|
||||
|
||||
\wordtable{
|
||||
\ordinaryword{word-prop}{word-prop ( word name -- value )}{words}\\
|
||||
|
@ -1226,7 +1229,7 @@ This is an even lower-level facility for working with the address containing nat
|
|||
\wordtable{
|
||||
\ordinaryword{update-xt}{update-xt ( word -- )}{words}
|
||||
}
|
||||
Updates a word's execution token according to its primitive number. When called with a compiled word, has the effect of decompiling the word. Calling \texttt{set-word-primitive} automatically updates this address.
|
||||
Updates a word's execution token according to its primitive number. When called with a compiled word, has the effect of decompiling the word. The execution token is automatically updated after a call to \texttt{set-word-primitive}.
|
||||
|
||||
\wordtable{
|
||||
\ordinaryword{recrossref}{recrossref ( word -- )}{words}
|
||||
|
@ -1237,9 +1240,22 @@ Updates the cross-referencing database, which you will probably need to do if yo
|
|||
|
||||
\glossary{name=object,
|
||||
description=a datum that can be identified}
|
||||
\mutableglos
|
||||
|
||||
Everything in Factor is an object, where an object is a collection of slots. Each object has a unique identity, and references to objects are passed by value on the stack. It is possible to have two references to the same object, and if the object is mutated through one reference, the changes will be visible through the other reference. Not all objects are mutable; the documentation for each class details if its instances are mutable or not.
|
||||
|
||||
\subsection{Identity and equality}
|
||||
|
||||
There are two distinct notions of ``sameness'' when it comes to objects. You can test if two references point to the same object, or you can test if two objects are equal in some sense, usually by having the same type and equal slot values.
|
||||
\wordtable{
|
||||
\ordinaryword{eq?}{eq?~( object object -- ?~)}{kernel}
|
||||
}
|
||||
Output \texttt{t} if two references point to the same object, and \texttt{f} otherwise.
|
||||
\wordtable{
|
||||
\genericword{=}{= ( object object -- ?~)}{kernel}
|
||||
}
|
||||
Output \texttt{t} if two objects are equal, and \texttt{f} otherwise. The precise meaning of equality depends on the object's class, however usually two objects are equal if their slot values are equal. If two objects are equal, they have the same printed representation, although the converse is not always true.
|
||||
|
||||
\subsection{Generic words and methods}
|
||||
|
||||
\glossary{name=generic word,
|
||||
|
@ -1265,13 +1281,34 @@ can potentially occur in a different source file.
|
|||
|
||||
\subsubsection{\label{method-order}Method ordering}
|
||||
|
||||
While not all classes are \emph{comparable}, meaning there is no canonical linear ordering for classes, the methods of a generic word are ordered, and you can inspect this order using the \texttt{order} word:
|
||||
If two classes have a non-empty intersection, there is no guarantee that one is a subclass of the other. This means there is no canonical linear ordering of classes. The methods of a generic word are linearly ordered, though, and you can inspect this order using the \texttt{order} word.
|
||||
|
||||
Suppose you have the following definitions:
|
||||
\begin{verbatim}
|
||||
GENERIC: foo
|
||||
M: integer foo 1 + ;
|
||||
M: number foo 1 - ;
|
||||
M: object foo dup 2list ;
|
||||
\end{verbatim}
|
||||
Since the \texttt{integer} class is strictly smaller than the \texttt{number} class, which in turn is strictly smaller than the \texttt{object} class, the ordering of methods is not surprising in this case:
|
||||
\begin{alltt}
|
||||
\textbf{ok} \bs = order .
|
||||
\textbf{[ object number sequence string cons sbuf alien tuple
|
||||
hashtable POSTPONE: f ]}
|
||||
\textbf{ok} \bs foo order .
|
||||
\textbf{[ object number integer ]}
|
||||
\end{alltt}
|
||||
Least-specific methods come first in the list.
|
||||
However, suppose we had the following set of definitions:
|
||||
\begin{verbatim}
|
||||
GENERIC: describe
|
||||
M: general-t describe drop "a true value" print ;
|
||||
M: general-list describe drop "a list" print ;
|
||||
M: object describe drop "an object" print ;
|
||||
\end{verbatim}
|
||||
Neither \texttt{general-t} nor \texttt{general-list} contains the other, and their intersection is the non-empty \texttt{cons} class. So the generic word system will place \texttt{object} first in the method order, however either \texttt{general-t} or \texttt{general-list} may come next, and it is pretty much a random choice that depends on hashing:
|
||||
\begin{alltt}
|
||||
\textbf{ok} \bs bar order .
|
||||
\textbf{[ object general-list general-t ]}
|
||||
\end{alltt}
|
||||
|
||||
Therefore, the outcome of calling \texttt{bar} with a cons cell is undefined.
|
||||
|
||||
\subsection{Classes}
|
||||
\glossary{name=class,
|
||||
|
@ -1371,7 +1408,7 @@ M: complex abs >rect mag2 ;
|
|||
\glossary{name=complement,
|
||||
description={a class whose set of instances is the set of objects that are not instances of a specific class}}
|
||||
|
||||
An object is an instance of a complement class if it is not an instance of the complement's parameter.
|
||||
An object is an instance of a complement if it is not an instance of the complement's parameter.
|
||||
\wordtable{
|
||||
\parsingword{COMPLEMENT:}{COMPLEMENT: \emph{name} \emph{parameter}}{syntax}
|
||||
}
|
||||
|
@ -1385,17 +1422,16 @@ COMPLEMENT: general-t f
|
|||
description={a word with stack effect \texttt{( object -- ?~)}, or more alternatively, a class whose instances are the instances of a superclass that satisfy an arbitrary predicate}}
|
||||
An object is an instance of a predicate classes if it is an instance of the predicate's parent class, and if it satisfies the predicate definition.
|
||||
|
||||
To speed up dispatch, each predicate must be
|
||||
defined as a subclass of some other class. That way predicates
|
||||
subclassing from disjoint builtin classes do not need to be
|
||||
exhaustively tested.
|
||||
Each predicate must be
|
||||
defined as a subclass of some other class. This ensures that predicates inheriting from disjoint classes do not need to be
|
||||
exhaustively tested during method dispatch.
|
||||
\wordtable{
|
||||
\parsingword{PREDICATE:}{PREDICATE: \emph{parent} \emph{name} \emph{predicate} ;}{syntax}
|
||||
}
|
||||
Defines a predicate class deriving from \texttt{parent} whose instances are the instances of \texttt{superclass} that satisfy the \texttt{predicate} quotation. The predicate quotation must have stack effect \texttt{( object -- ?~)}.
|
||||
|
||||
For example, the library defines some subclasses of \texttt{integer}
|
||||
classifying ASCII characters:
|
||||
For example, the \texttt{strings} vocabulary contains subclasses of \texttt{integer}
|
||||
classifying various ASCII characters:
|
||||
\begin{verbatim}
|
||||
PREDICATE: integer blank " \t\n\r" str-contains? ;
|
||||
PREDICATE: integer letter CHAR: a CHAR: z between? ;
|
||||
|
@ -1407,7 +1443,7 @@ PREDICATE: integer printable CHAR: \s CHAR: ~ between? ;
|
|||
\subsubsection{Operations on classes}
|
||||
\wordtable{
|
||||
\ordinaryword{class-and}{class-and ( class class -- class )}{kernel}\\
|
||||
\ordinaryword{class-or}{class-and ( class class -- class )}{kernel}
|
||||
\ordinaryword{class-or}{class-or ( class class -- class )}{kernel}
|
||||
}
|
||||
Intersection and union of classes. Note that the returned class might not be the exact desired class; for example, \texttt{object} is output if no suitable class definition could be found at all.
|
||||
\wordtable{
|
||||
|
@ -1422,9 +1458,9 @@ Tuples are user-defined classes composed of named slots. All tuples have the sam
|
|||
\wordtable{
|
||||
\parsingword{TUPLE:}{TUPLE: \emph{name} \emph{slots} ;}{syntax}
|
||||
}
|
||||
Defines a new tuple class, along with a predicate \texttt{name?}~and default constructor \texttt{<name>}.
|
||||
Defines a new tuple class with membership predicate \texttt{name?}~and constructor \texttt{<name>}.
|
||||
|
||||
Slots are read and written using various automatically-defined words with names of the
|
||||
The constructor takes slots in left-to-right order from the stack. After construction, slots are read and written using various automatically-defined words with names of the
|
||||
form \texttt{\emph{class}-\emph{slot}} and \texttt{set-\emph{class}-\emph{slot}}.
|
||||
|
||||
Here is an example:
|
||||
|
@ -1448,8 +1484,8 @@ produces a new \texttt{point}:
|
|||
|
||||
\subsubsection{Constructors}
|
||||
|
||||
A tuple constructor is named after the tuple class surrounded in angle
|
||||
brackets (\texttt{<} and \texttt{>}). A default constructor is provided
|
||||
Constructors are named after the tuple class surrounded in angle
|
||||
brackets (\texttt{<}~and~\texttt{>}). A default constructor is provided
|
||||
that reads slot values from the stack, however a custom constructor can
|
||||
be defined using the \texttt{C:} parsing word.
|
||||
\wordtable{
|
||||
|
@ -1480,7 +1516,40 @@ Factor uses delegation is used instead of inheritance, but it is not a direct
|
|||
substitute; in particular, the semantics differ in that a delegated
|
||||
method call receives the delegate on the stack, not the original object.
|
||||
|
||||
\section{Numbers}
|
||||
\section{Sequences}
|
||||
|
||||
\glossary{name=sequence,
|
||||
description=an object storing a linearly-ordered set of elements}
|
||||
|
||||
\subsection{Sequence operations}
|
||||
|
||||
\subsection{Sequence combinators}
|
||||
|
||||
\subsection{Lists and cons cells}
|
||||
|
||||
\subsubsection{List operations}
|
||||
|
||||
\subsubsection{Constructing and destructuring lists}
|
||||
|
||||
\subsubsection{Queues}
|
||||
|
||||
\subsection{Vectors}
|
||||
|
||||
\subsection{Strings}
|
||||
|
||||
\subsection{String buffers}
|
||||
|
||||
\subsection{Constructing sequences}
|
||||
|
||||
\section{Mappings}
|
||||
|
||||
\subsection{Association lists}
|
||||
|
||||
\subsection{Hashtables}
|
||||
|
||||
\subsection{\label{namespaces}Namespaces}
|
||||
|
||||
\section{Mathematics}
|
||||
|
||||
\numberglos
|
||||
|
||||
|
@ -2460,6 +2529,6 @@ The compiler consists of multiple stages -- first, a dataflow graph is inferred,
|
|||
|
||||
\printglossary
|
||||
|
||||
\input{spec.ind}
|
||||
\input{handbook.ind}
|
||||
|
||||
\end{document}
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
#!/bin/sh
|
||||
cd doc/
|
||||
pdflatex handbook
|
||||
./makeglos handbook
|
||||
makeindex handbook
|
||||
pdflatex handbook
|
||||
pdflatex handbook
|
||||
pdflatex handbook
|
|
@ -13,6 +13,8 @@ BUILTIN: cons 2 [ 0 "car" f ] [ 1 "cdr" f ] ;
|
|||
M: f car ;
|
||||
M: f cdr ;
|
||||
|
||||
GENERIC: >list ( seq -- list )
|
||||
|
||||
: swons ( cdr car -- [[ car cdr ]] )
|
||||
#! Push a new cons cell. If the cdr is f or a proper list,
|
||||
#! has the effect of prepending the car to the cdr.
|
||||
|
|
|
@ -14,6 +14,9 @@ M: cons nth ( n list -- element )
|
|||
1 - r> cdr nth
|
||||
] ifte ;
|
||||
|
||||
M: f empty? drop t ;
|
||||
M: cons empty? drop f ;
|
||||
|
||||
: 2list ( a b -- [ a b ] )
|
||||
unit cons ;
|
||||
|
||||
|
@ -26,9 +29,6 @@ M: cons nth ( n list -- element )
|
|||
: 3unlist ( [ a b c ] -- a b c )
|
||||
uncons uncons car ;
|
||||
|
||||
: append ( [ list1 ] [ list2 ] -- [ list1 list2 ] )
|
||||
over [ >r uncons r> append cons ] [ nip ] ifte ;
|
||||
|
||||
: contains? ( obj list -- ? )
|
||||
#! Test if a list contains an element equal to an object.
|
||||
[ = ] some-with? >boolean ;
|
||||
|
@ -71,7 +71,7 @@ M: cons nth ( n list -- element )
|
|||
#! list.
|
||||
2dup contains? [ nip ] [ cons ] ifte ;
|
||||
|
||||
: reverse ( list -- list )
|
||||
M: general-list reverse ( list -- list )
|
||||
[ ] swap [ swons ] each ;
|
||||
|
||||
: map ( list quot -- list )
|
||||
|
@ -97,9 +97,7 @@ M: cons nth ( n list -- element )
|
|||
|
||||
: prune ( list -- list )
|
||||
#! Remove duplicate elements.
|
||||
dup [
|
||||
uncons prune 2dup contains? [ nip ] [ cons ] ifte
|
||||
] when ;
|
||||
dup [ uncons prune unique ] when ;
|
||||
|
||||
: all=? ( list -- ? )
|
||||
#! Check if all elements of a list are equal.
|
||||
|
|
|
@ -20,7 +20,7 @@ M: sbuf = sbuf= ;
|
|||
>r over length - dup 0 <= [
|
||||
r> 2drop
|
||||
] [
|
||||
r> fill swap seq-append
|
||||
r> fill swap append
|
||||
] ifte ;
|
||||
|
||||
: split-next ( index string split -- next )
|
||||
|
@ -58,5 +58,5 @@ M: sbuf = sbuf= ;
|
|||
|
||||
: ch>string ( ch -- str ) 1 <sbuf> [ push ] keep sbuf>string ;
|
||||
|
||||
M: string unfreeze >sbuf ;
|
||||
M: string thaw >sbuf ;
|
||||
M: string freeze drop sbuf>string ;
|
||||
|
|
|
@ -11,10 +11,10 @@ vectors ;
|
|||
UNION: sequence array string sbuf vector ;
|
||||
|
||||
M: object ensure-capacity 2drop ;
|
||||
M: object unfreeze clone ;
|
||||
M: object thaw clone ;
|
||||
M: object freeze drop ;
|
||||
|
||||
: empty? ( seq -- ? ) length 0 = ;
|
||||
M: object empty? ( seq -- ? ) length 0 = ;
|
||||
|
||||
: (>list) ( n i seq -- list )
|
||||
pick pick <= [
|
||||
|
@ -74,8 +74,7 @@ M: sequence (tree-each) [ (tree-each) ] seq-each-with ;
|
|||
0 swap (nmap) ; inline
|
||||
|
||||
: immutable ( seq quot -- seq | quot: seq -- )
|
||||
swap [ unfreeze ] keep >r dup >r swap call r> r> freeze ;
|
||||
inline
|
||||
swap [ thaw ] keep >r dup >r swap call r> r> freeze ; inline
|
||||
|
||||
: seq-map ( seq quot -- seq | quot: elt -- elt )
|
||||
swap [ swap nmap ] immutable ; inline
|
||||
|
@ -114,14 +113,20 @@ M: sequence (tree-each) [ (tree-each) ] seq-each-with ;
|
|||
! over length over ensure-capacity
|
||||
[ over push ] seq-each drop ;
|
||||
|
||||
: seq-append ( s1 s2 -- s1+s2 )
|
||||
: append ( s1 s2 -- s1+s2 )
|
||||
#! Return a new sequence of the same type as s1.
|
||||
swap [ swap nappend ] immutable ;
|
||||
|
||||
: seq-append3 ( s1 s2 s3 -- s1+s2+s3 )
|
||||
: append3 ( s1 s2 s3 -- s1+s2+s3 )
|
||||
#! Return a new sequence of the same type as s1.
|
||||
rot [ [ rot nappend ] keep swap nappend ] immutable ;
|
||||
|
||||
: concat ( list -- seq )
|
||||
#! Append together a list of sequences.
|
||||
dup empty? [
|
||||
unswons [ swap [ nappend ] each-with ] immutable
|
||||
] unless ;
|
||||
|
||||
: peek ( sequence -- element )
|
||||
#! Get value at end of sequence.
|
||||
dup length 1 - swap nth ;
|
||||
|
@ -148,6 +153,8 @@ M: sequence (tree-each) [ (tree-each) ] seq-each-with ;
|
|||
#! Destructively reverse seq.
|
||||
dup length 2 /i [ 2dup (nreverse) ] repeat drop ;
|
||||
|
||||
M: object reverse ( seq -- seq ) [ nreverse ] immutable ;
|
||||
|
||||
! Equality testing
|
||||
: length= ( seq seq -- ? ) length swap length number= ;
|
||||
|
||||
|
|
|
@ -11,11 +11,14 @@ USING: generic kernel math strings vectors ;
|
|||
! kernel-internals vocabulary, so don't use them unless you have
|
||||
! a good reason.
|
||||
|
||||
GENERIC: empty? ( sequence -- ? )
|
||||
GENERIC: length ( sequence -- n )
|
||||
GENERIC: set-length ( n sequence -- )
|
||||
GENERIC: ensure-capacity ( n sequence -- )
|
||||
GENERIC: nth ( n sequence -- obj )
|
||||
GENERIC: set-nth ( value n sequence -- obj )
|
||||
GENERIC: >list ( seq -- list )
|
||||
GENERIC: unfreeze ( seq -- mutable-seq )
|
||||
GENERIC: thaw ( seq -- mutable-seq )
|
||||
GENERIC: freeze ( new orig -- new )
|
||||
GENERIC: reverse ( seq -- seq )
|
||||
|
||||
DEFER: append ! remove this when sort is moved from lists to sequences
|
||||
|
|
|
@ -29,3 +29,6 @@ IN: vectors
|
|||
#! vector. For example, if n=1, this returns a vector of
|
||||
#! one element.
|
||||
[ length swap - ] keep vector-tail ;
|
||||
|
||||
M: general-list thaw >vector ;
|
||||
M: general-list freeze drop >list ;
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
IN: generic
|
||||
USING: errors hashtables kernel lists math parser strings
|
||||
vectors words ;
|
||||
sequences vectors words ;
|
||||
|
||||
! Complement metaclass, contains all objects not in a certain class.
|
||||
SYMBOL: complement
|
||||
|
|
|
@ -2,7 +2,8 @@
|
|||
! See http://factor.sf.net/license.txt for BSD license.
|
||||
IN: generic
|
||||
USING: errors hashtables kernel kernel-internals lists
|
||||
namespaces parser strings words vectors math math-internals ;
|
||||
namespaces parser sequences strings words vectors math
|
||||
math-internals ;
|
||||
|
||||
! A simple single-dispatch generic word system.
|
||||
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
! Copyright (C) 2004, 2005 Slava Pestov.
|
||||
! See http://factor.sf.net/license.txt for BSD license.
|
||||
IN: generic
|
||||
USING: errors hashtables kernel lists namespaces parser strings
|
||||
words vectors ;
|
||||
USING: errors hashtables kernel lists namespaces parser
|
||||
sequences strings words vectors ;
|
||||
|
||||
! Union metaclass for dispatch on multiple classes.
|
||||
SYMBOL: union
|
||||
|
|
|
@ -27,7 +27,8 @@
|
|||
IN: browser-responder
|
||||
USING: html cont-responder kernel stdio namespaces words lists
|
||||
streams strings inspector kernel prettyprint words html parser
|
||||
errors unparser listener url-encoding hashtables memory ;
|
||||
errors unparser listener url-encoding hashtables memory
|
||||
sequences ;
|
||||
|
||||
: <browser> ( allow-edit? vocab word -- )
|
||||
#! An object for storing the current browser
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
IN: cont-responder
|
||||
USING: stdio httpd httpd-responder math random namespaces streams
|
||||
lists strings kernel html url-encoding unparser hashtables
|
||||
parser generic ;
|
||||
parser generic sequences ;
|
||||
|
||||
#! Used inside the session state of responders to indicate whether the
|
||||
#! next request should use the post-refresh-get pattern. It is set to
|
||||
|
@ -109,15 +109,10 @@ TUPLE: item expire? quot id time-added ;
|
|||
#! a certain period of time if 'expire?' is true.
|
||||
get-random-id -rot pick continuation-item over continuation-table set-hash ;
|
||||
|
||||
: append* ( lists -- list )
|
||||
#! Given a list of lists, append the lists together
|
||||
#! and return the concatenated list.
|
||||
f swap [ append ] each ;
|
||||
|
||||
: register-continuation* ( expire? quots -- id )
|
||||
#! Like register-continuation but registers a quotation
|
||||
#! that will call all quotations in the list, in the order given.
|
||||
append* register-continuation ;
|
||||
concat register-continuation ;
|
||||
|
||||
: get-continuation-item ( id -- <item> )
|
||||
#! Get the continuation item associated with the id.
|
||||
|
|
|
@ -30,6 +30,7 @@ USE: kernel
|
|||
USE: stdio
|
||||
USE: namespaces
|
||||
USE: words
|
||||
USE: sequences
|
||||
|
||||
! These words are used to provide a means of writing
|
||||
! formatted HTML to standard output with a familiar 'html' look
|
||||
|
|
|
@ -12,7 +12,7 @@ sequences strings vectors words hashtables prettyprint ;
|
|||
|
||||
: add-inputs ( count stack -- stack )
|
||||
#! Add this many inputs to the given stack.
|
||||
[ length - computed-value-vector ] keep seq-append ;
|
||||
[ length - computed-value-vector ] keep append ;
|
||||
|
||||
: unify-lengths ( list -- list )
|
||||
#! Pad all vectors to the same length. If one vector is
|
||||
|
|
|
@ -107,8 +107,8 @@ M: computed literal-value ( value -- )
|
|||
: ensure-d ( typelist -- )
|
||||
dup meta-d get ensure-types
|
||||
meta-d get required-inputs >vector dup
|
||||
meta-d [ seq-append ] change
|
||||
d-in [ seq-append ] change ;
|
||||
meta-d [ append ] change
|
||||
d-in [ append ] change ;
|
||||
|
||||
: (present-effect) ( vector -- list )
|
||||
>list [ value-class ] map ;
|
||||
|
|
|
@ -108,7 +108,7 @@ SYMBOL: parser-stream
|
|||
: <actions> ( path alist -- alist )
|
||||
#! For each element of the alist, change the value to
|
||||
#! path " " value
|
||||
[ uncons >r swap " " r> seq-append3 cons ] map-with ;
|
||||
[ uncons >r swap " " r> append3 cons ] map-with ;
|
||||
|
||||
DEFER: <file-reader>
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
! Copyright (C) 2004, 2005 Slava Pestov.
|
||||
! See http://factor.sf.net/license.txt for BSD license.
|
||||
IN: parser
|
||||
USING: kernel lists namespaces streams strings ;
|
||||
USING: kernel lists namespaces sequences streams strings ;
|
||||
|
||||
: file-vocabs ( -- )
|
||||
"file-in" get "in" set
|
||||
|
|
|
@ -4,7 +4,8 @@
|
|||
! Bootstrapping trick; see doc/bootstrap.txt.
|
||||
IN: !syntax
|
||||
USING: alien errors generic hashtables kernel lists math
|
||||
namespaces parser strings syntax unparse vectors words ;
|
||||
namespaces parser sequences strings syntax unparse vectors
|
||||
words ;
|
||||
|
||||
: parsing ( -- )
|
||||
#! Mark the most recently defined word to execute at parse
|
||||
|
@ -24,7 +25,7 @@ namespaces parser strings syntax unparse vectors words ;
|
|||
|
||||
! The canonical t is a heap-allocated dummy object. It is always
|
||||
! the first in the image.
|
||||
BUILTIN: t 14 ; : t t swons ; parsing
|
||||
BUILTIN: t 7 ; : t t swons ; parsing
|
||||
|
||||
! In the runtime, the canonical f is represented as a null
|
||||
! pointer with tag 3. So
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
! Copyright (C) 2005 Slava Pestov.
|
||||
! See http://factor.sf.net/license.txt for BSD license.
|
||||
IN: parser
|
||||
USING: kernel lists namespaces words ;
|
||||
USING: kernel lists namespaces sequences words ;
|
||||
|
||||
: parse-loop ( -- )
|
||||
scan-word [
|
||||
|
|
|
@ -152,3 +152,8 @@ M: number union-containment drop 2 ;
|
|||
|
||||
[ 1 ] [ 1 union-containment ] unit-test
|
||||
[ 2 ] [ 1.0 union-containment ] unit-test
|
||||
|
||||
! Testing recovery from bad method definitions
|
||||
"GENERIC: unhappy" eval
|
||||
[ "M: vocabularies unhappy ;" eval ] unit-test-fails
|
||||
[ ] [ "GENERIC: unhapy" eval ] unit-test
|
||||
|
|
|
@ -46,7 +46,10 @@ sequences strings test vectors ;
|
|||
[ t ] [ { } hashcode { } hashcode = ] unit-test
|
||||
|
||||
[ { 1 2 3 } { 1 2 3 4 5 6 } ]
|
||||
[ { 1 2 3 } dup { 4 5 6 } seq-append ] unit-test
|
||||
[ { 1 2 3 } dup { 4 5 6 } append ] unit-test
|
||||
|
||||
[ f ] [ f concat ] unit-test
|
||||
[ { 1 2 3 4 } ] [ [ { 1 } [ 2 ] { 3 4 } ] concat ] unit-test
|
||||
|
||||
[ { "" "a" "aa" "aaa" } ]
|
||||
[ 4 [ CHAR: a fill ] vector-project ]
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
! Copyright (C) 2003, 2005 Slava Pestov.
|
||||
! See http://factor.sf.net/license.txt for BSD license.
|
||||
IN: listener
|
||||
USING: errors kernel lists math memory namespaces parser stdio
|
||||
strings presentation words unparser vectors ansi ;
|
||||
USING: errors kernel lists math memory namespaces parser
|
||||
sequences stdio strings presentation words unparser vectors ansi ;
|
||||
|
||||
SYMBOL: cont-prompt
|
||||
SYMBOL: listener-prompt
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
! Copyright (C) 2005 Slava Pestov.
|
||||
! See http://factor.sf.net/license.txt for BSD license.
|
||||
IN: gadgets
|
||||
USING: alien generic kernel lists math namespaces sdl ;
|
||||
USING: alien generic kernel lists math namespaces sdl sequences ;
|
||||
|
||||
GENERIC: handle-event ( event -- )
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
! See http://factor.sf.net/license.txt for BSD license.
|
||||
IN: gadgets
|
||||
USING: alien generic kernel lists math namespaces prettyprint
|
||||
sdl stdio ;
|
||||
sequences sdl stdio ;
|
||||
|
||||
DEFER: pick-up
|
||||
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
! Copyright (C) 2005 Slava Pestov.
|
||||
! See http://factor.sf.net/license.txt for BSD license.
|
||||
IN: gadgets
|
||||
USING: generic hashtables kernel lists math namespaces ;
|
||||
USING: generic hashtables kernel lists math namespaces
|
||||
sequences ;
|
||||
|
||||
: remove-gadget ( gadget box -- )
|
||||
[ 2dup gadget-children remq swap set-gadget-children ] keep
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
! Copyright (C) 2005 Slava Pestov.
|
||||
! See http://factor.sf.net/license.txt for BSD license.
|
||||
IN: gadgets
|
||||
USING: generic kernel lists math namespaces ;
|
||||
USING: generic kernel lists math namespaces sequences ;
|
||||
|
||||
: hide-menu ( -- )
|
||||
world get
|
||||
|
|
Loading…
Reference in New Issue