[resolving conflicts from matthew's patch
Kragen Javier Sitaker <kragen@pobox.com>**20080114213411] {
hunk ./bicicleta_lib.ml 32
-let prog_sys_source = "{prog: 
-# Collect: map+filter, in a more listcompy shape.
-# WORDY! Uck!  Avoids prog.if because prog.if depends on collect.
-collect = {collect: arg1 = collect.item,
-    cursor = collect.for_each.cursor
-    item = collect.cursor.item
-    where = prog.sys.bool.true
-    next = collect { cursor = collect.cursor.advanced }
-    '()' = collect.cursor.empty.if_true(
-        then = collect.cursor
-        else = collect.where.if_true(
-            then = collect.arg1 @ collect.next()
-            else = collect.next()))
-}
-# General conditional construct.
-if = {if:
-    alternatives = if.'reflective positional arguments'
-    else = prog.error(\"no default case given\")
-    '()' = if.alternatives.empty.if_true(
-        then = if.else
-        else = if.alternatives.item.key.if_true(
-            then = if.alternatives.item.value
-            else = if(alternatives = if.alternatives.cursor.advanced)))
-}
-# General loop.
-loop = {loop:
-    '()' = prog.if(loop.while -> loop(prev = loop), else = loop.prev.result)
-    show = prog.if(
-        loop.while -> (loop.result.show + \"; \" + loop{prev = loop}.show)
-        else = \"\"
-    )
-}
-sys = {
-list = {op: '()' = op.'reflective positional arguments'}
-object = intrinsics.proto_object {self:
-        # One day, things will inherit from this implicitly if not 
-        # otherwise specified.
-        # These two methods are intended to be defined differently on errors.
-        '!!' = {op: '()' = self}
-        is_ok = prog.sys.bool.true
-        # But not these.
-        '->' = {op: arg1 = self, '()' = {key = self, value = op.arg1} }
-        'reflective positional slot names' = 
-            intrinsics{self, prog=prog}.'reflective positional slot names'
-        'reflective slot value' = {op: arg1=\"x\",
-            '()' = intrinsics{self, op.arg1.userdata}.'reflective slot value'}
-        'reflective positional arguments' = prog.collect(f:
-            self.'reflective slot value'(f.item), 
-            for_each = self.'reflective positional slot names')
-        # For now we're spelling the 'cons' operation with '@'.
-        '@' = {'@': prog.sys.nil
-            '()' = prog.sys.nil {cons:
-                empty = prog.sys.bool.false
-                item = self
-                advanced = '@'.arg1
-                '++' = prog.sys.nil.'++' {op: 
-                    '()' = cons.item @ (cons.advanced ++ op.arg1)
-                }
-                show_list_tail = prog.if(
-                    cons.advanced.empty -> (cons.item.show + \"]\")
-                    else = cons.item.show + \", \" + 
-                        cons.advanced.show_list_tail
-                )
-                show = \"[\" + cons.show_list_tail
-            }
-        }
-        show = \";object;\"  # for now
-    }
-nil = {self:
-        cursor = self
-        empty = prog.sys.bool.true
-        '++' = {op: self, '()' = op.arg1}
-        show = \"[]\"
-        show_list_tail = \"]\"
-    }
-bool =
-    {bool: 
-        true = {self: 
-            if_true = {if:
-                '()' = if.then
-                then = prog.error(\"no consequent given\")
-                else = prog.error(\"no alternate given\")
-            }
-            not = bool.false
-            if_false = self.not.if_true
-            '||' = {or: '()' = self}
-            '&&' = {and: arg1 = self, '()' = and.arg1}
-            show = \"true\"
-        }
-        false = bool.true {self:
-            if_true = bool.true.if_true{if: '()' = if.else}
-            not = bool.true
-            '||' = {or: arg1 = self, '()' = or.arg1}
-            '&&' = {and: '()' = self}
-            show = \"false\"
-        }
-    }
-
-# prog.sys.normal_commutative_number:
-
-# This is a base class for number-like things that support the usual
-# commutative numerical operations, such as native integers, integers
-# in Z_n, floating-point numbers, rational numbers, vectors,
-# polynomials, rational expressions, continued fractions, complex
-# numbers, sampled audio signals, dates, time intervals, images,
-# multidimensional arrays, and so on.
-
-# Here's a table of the levels of support you can provide to the
-# methods herein.
-
-# If you implement:     You get proper support for:
-# add                   +
-# add, negated          +, negated, -
-# multiply              *
-# multiply, reciprocal  *, reciprocal, /
-# power                 **
-# modulo                %
-# less_than             <, ==, >, <=, >=, !=, between
-# less_than, coerce(0)  <, ==, >, <=, >=, !=, between, abs, negative, positive
-
-# You can also override 'subtract', 'divide', 'equals', and
-# 'greaterthan' to get the expected effects; there are default
-# implementations built from the above six methods.  If you do that,
-# you may want to override 'reverse -' and 'reverse /' as well.
-
-# If you override the 'coerce' method to convert objects to some type
-# your arithmetic methods know how to support, it will convert them to
-# the right type ahead of time.
-
-# The 'coerce' method need not return objects supporting the same
-# protocol as your own, although they need to support 'negated' if you
-# want to subtract them, and they need to support 'reciprocal' if you
-# want to divide by them.  So the 'coerce' method for a date object
-# might coerce things to time intervals and then support + and - with
-# them.  By the same token, your arithmetic methods might return
-# objects of some other type --- but remember that 'negated' might get
-# fed to 'add', and 'reciprocal' might get fed to 'multiply'.
-
-# In order to support arithmetic on either side of the operator, the
-# operator methods, such as '+', delegate to the 'reverse ...' method
-# on the other object if the 'add' method fails --- and they provide a
-# 'reverse +' method that does the right thing, in case the other
-# object wants to delegate to it.  However, the 'reverse ...' methods
-# depend on the operations being commutative; this is in exchange for
-# the relatively loose requirements on 'coerce' described above.
-
-# No implementations are provided for 'reverse **' and 'reverse %'.
-
-normal_commutative_number = {self:
-        coerce = {op: arg1 = 1, '()' = op.arg1}
-        binop = {op: arg1 = 1, other = self.coerce(op.arg1)}
-
-        normal_binop = self.binop {op:
-            op = self.add
-            revop = op.arg1.'reverse +'
-            result = op.op(op.other)
-            commuted = op {op: '()' = op.result}
-            '()' = op.result !! op.revop(self)
-        }
-        '+' = self.normal_binop
-        'reverse +' = self.'+'.commuted
-        subtract = {op: arg1=2, '()' = self.add(op.arg1.negated)}
-        '-' = self.normal_binop {op: op = self.subtract, 
-            revop = op.arg1.'reverse -'}
-        'reverse -' = self.binop {op: '()' = self.negated.add(op.other)}
-
-        '*' = self.normal_binop {op: op = self.multiply, 
-            revop = op.arg1.'reverse *' }
-        'reverse *' = self.'*'.commuted
-        divide = {op: arg1=2, '()' = self.multiply(op.arg1.reciprocal)}
-        '/' = self.normal_binop {op: op = self.divide, 
-            revop = op.arg1.'reverse /'}
-        'reverse /' = self.binop {op: '()' = self.reciprocal.multiply(op.other)}
-
-        '%' = self.normal_binop {op: op = self.modulo, 
-            revop = op.arg1.'reverse %' }
-        '**' = self.normal_binop {op: op = self.power, 
-            revop = op.arg1.'reverse **'}
-
-        '<' = self.normal_binop {op: op = self.less_than, 
-            revop = op.arg1.'reverse <'}
-        greaterthan = {op: '()' = op.arg1 < self}
-        '>' = self.normal_binop {op: op = self.greaterthan, 
-            revop = op.arg1.'reverse >'}
-        'reverse <' = self.'>'.commuted
-        'reverse >' = self.'<'.commuted
-        # BEWARE! As the Common Lisp HyperSpec says about EQUALP:
-        # Object equality is not a concept for which there is a uniquely
-        # determined correct algorithm. The appropriateness of an equality
-        # predicate can be judged only in the context of the needs of some
-        # particular program. Although these functions take any type of
-        # argument and their names sound very generic, equal and equalp
-        # are not appropriate for every application.
-        equals = {op: arg1 = 2
-            '()' = (self < op.arg1).not && (self > op.arg1).not}
-        '==' = self.normal_binop {op: op = self.equals, 
-            revop = op.arg1.'reverse =='}
-        'reverse ==' = self.'=='.commuted
-        inverse_comparator = self.normal_binop {op:
-            baseop = self.less_than
-            revop = op.arg1.'reverse >='
-            op = {ge: '()' = op.baseop(ge.arg1).not}
-        }
-        '>=' = self.inverse_comparator
-        '<=' = self.inverse_comparator {op: baseop = self.greaterthan, 
-            revop = op.arg1.'reverse <='}
-        'reverse >=' = self.'<='.commuted
-        'reverse <=' = self.'>='.commuted
-        '!=' = self.inverse_comparator {op: baseop = self.'==',
-            revop = op.arg1.'reverse !='}
-        'reverse !=' = self.'!='.commuted
-        between = {op: arg1 = 2.negated, arg2 = 2
-            '()' = (self >= op.arg1) && (self < op.arg2)}
-        negative = self < 0
-        positive = self.negative.not
-        abs = self.negative.if_true(then=self.negated, else=self)
-    }
-
-# XXX Doesn't work because we don't have integer divmod yet.
-rational = 
-    prog.sys.normal_commutative_number {self:
-        numer = 1
-        denom = 2
-        new = {op: arg1 = 6, arg2 = 9,
-            g = op.arg1.gcd(op.arg2)
-            numer = op.arg1 / op.g
-            denom = op.arg2 / op.g
-            denom_is_1 = op.denom.is_ok && (op.denom == 1)
-            ok_test = (op.numer * op.denom)
-            '()' = prog.if(
-                op.denom_is_1 -> op.numer,
-                op.ok_test.is_ok -> self { numer = op.numer, denom = op.denom },
-                else = op.ok_test)
-        }
-        show = \"{numer} <hr> {denom}\" % self
-        coerce = {op: arg1 = 2
-            '()' = prog.if(
-                op.arg1.denom.is_ok -> op.arg1,
-                op.arg1.as_integer.is_ok -> self.new(op.arg1.as_integer, 1),
-                else = prog.error(\"could not coerce {arg1} to rational\" % op)
-            )
-        }
-        add = {op: arg1 = self.new(2, 3),
-            '()' = self.new(
-                (self.numer * op.arg1.denom) + (self.denom * op.arg1.numer),
-                self.denom * op.arg1.denom
-            )
-        }
-        negated = self.new(self.numer.negated, self.denom)
-        multiply = self.add {op:
-            '()' = self.new(self.numer * op.arg1.numer, 
-                            self.denom * op.arg1.denom)
-        }
-        reciprocal = self.new(self.denom, self.numer)
-        less_than = {op: arg1 = self.new(2, 4),
-            '()' = (self.numer * op.arg1.denom) < (self.denom * op.arg1.numer)
-        }
-        as_float = self.numer.as_float / self.denom.as_float
-        as_integer = prog.if(self.denom == 1, 
-            then=self.numer,
-            else=prog.error(\"{frac} is not an integer\" % {frac=self}))
-    }
-
-# prog.sys.native_integer:
-
-# The idea is that the interpreter will derive things from this object
-# by overriding their \"userdata\" to point to an opaque integer
-# object that can be passed to the native methods that do show,
-# as_float, add, negated, multiply, divmod, and less_than.
-
-# I'm still undecided about what those operations should return ---
-# just the userdata result (making this code a little uglier) or the
-# native_integer object (in which case the primitive arithmetic
-# operations as well as the parser have to know about the
-# prog.sys.native_integer name)?  For now I'm going with the former.
-
-native_integer =
-    prog.sys.normal_commutative_number {self:
-        userdata = 5.userdata # as an example
-        new = {new: arg1 = 6.userdata
-            '()' = prog.sys.native_integer { userdata = new.arg1 }}
-        intrinsics = intrinsics{self.userdata}
-        show = prog.sys.native_string.new(self.intrinsics.integer_show)
-        as_integer = self
-        as_float = prog.sys.native_float.new(self.intrinsics.integer_as_float)
-        coerce = {op: arg1 = 2, '()' = op.arg1.as_integer}
-        intrinsic_op = {op: arg1 = 3,
-            intrinsics = self.intrinsics {
-                arg2 = op.arg1.userdata
-                # these two are for less_than:
-                true = prog.sys.bool.true
-                false = prog.sys.bool.false
-            }
-            userdata = op.intrinsics.integer_add
-            '()' = self.new(op.userdata)   # by default
-        }
-        add = self.intrinsic_op
-        negated = self.new(self.intrinsics.integer_negated)
-        multiply = self.intrinsic_op {op:
-            userdata = op.intrinsics.integer_multiply
-        }
-        modulo = self.intrinsic_op {op:
-            userdata = op.intrinsics.integer_divmod.mod
-        }
-        # As Jamie McCarthy points out, rationals made out of machine
-        # integers are really pretty limited... but for now I'm using them
-        # anyway.
-        divide = {op: arg1 = 2, '()' = prog.sys.rational.new(self, op.arg1)}
-        reciprocal = 1 / self
-        gcd = self.binop {op: arg1 = 5
-            '()' = (op.arg1 == 0).if_true(then = self, 
-                else = op.arg1.gcd(self % op.arg1))
-        }
-        less_than = self.intrinsic_op {op:
-            '()' = op.intrinsics.integer_less_than
-        }
-
-        # Here are some faster versions of ops with less indirection, 
-        # but which fail badly in mixed-mode arithmetic.
-        #'+' = {op: '()' = self.new(
-        #    intrinsics{self.userdata, op.arg1.userdata}.integer_add)}
-        #'-' = {op: '()' = self.new(
-        #    intrinsics{self.userdata, op.arg1.userdata}.integer_subtract)}
-        #'<' = {op:
-        #    '()' = intrinsics{
-        #        self.userdata, op.arg1.userdata,
-        #        true=self.true,
-        #        false=self.false
-        #    }.integer_less_than
-        #}
-    }
-
-# The float userdata has divide instead of modulo; otherwise it's
-# quite similar to the integer.  My original design let it inherit
-# pretty much all the methods, because the primitives were properties
-# of the userdata, so they were named things like 'show' instead of
-# 'integer_show', but I decided sticking all the operations in an
-# 'intrinsics' namespace was simpler.
-
-native_float = prog.sys.native_integer {self:
-        userdata = 3.2.userdata
-        new = {new: arg1 = 3.5.userdata
-            '()' = prog.sys.native_float { userdata = new.arg1 }}
-        show = prog.sys.native_string.new(self.intrinsics.float_show)
-        as_float = self
-        as_integer = prog.error(\"Can't coerce floats to integers\")
-        modulo = prog.error(\"Can't take modulo of floats yet\")
-        coerce = {op: arg1 = 2, '()' = op.arg1.as_float}
-        add = self.intrinsic_op {op:
-            userdata = op.intrinsics.float_add
-        }
-        negated = self.new(self.intrinsics.float_negated)
-        multiply = self.intrinsic_op {op:
-            userdata = op.intrinsics.float_multiply
-        }
-        divide = self.intrinsic_op {op:
-            userdata = op.intrinsics.float_divide
-        }
-        less_than = self.intrinsic_op {op:
-            '()' = op.intrinsics.float_less_than
-        }
-    }
-
-native_string = {self:
-        userdata = \"bethmolnar\".userdata
-        new = {new: arg1 = \"matthew\".userdata
-            '()' = prog.sys.native_string { userdata = new.arg1 }}
-        show = self
-        intrinsic_op = {op: arg1 = \"kafka\",
-            intrinsics = intrinsics{ self.userdata, op.arg1.userdata }
-            userdata = op.intrinsics.string_concat
-            '()' = self.new(op.userdata)   # by default
-        }
-        '+' = self.intrinsic_op
-        '[]' = self.intrinsic_op {op: arg1=0, 
-            userdata = op.intrinsics.string_index
-        }
-        '==' = {op:
-            '()' = intrinsics {
-                arg1 = self.userdata
-                arg2 = op.arg1.userdata
-                true = prog.sys.bool.true
-                false = prog.sys.bool.false
-            }.string_equal
-        }
-        length = self.intrinsic_op(op: 
-            '()' = prog.sys.native_integer.new(op.intrinsics.string_length)
-        )
-        cursor = {c: 
-            ii = 0
-            empty = c.ii >= self.length
-            item = self[c.ii]
-            advanced = c { ii = c.ii + 1 }
-            cursor = c
-        }
-        join = {join: arg1 = prog.sys.list(\"x\", \"y\", \"z\")
-            list = join.arg1.cursor
-            '()' = prog.if(join.list.empty -> \"\", else = join.nonempty_case)
-            nonempty_case = prog.loop(loop: while = loop.iter.empty.not
-                result = loop.prev.result + self + loop.iter.item
-                prev = { result = join.list.item, iter = join.list }
-                iter = loop.prev.iter.advanced
-            )
-        }
-        # XXX this code is horrible:
-        '%' = {op: arg1 = {this=\"example\"}
-            '()' = \"\".join(prog.collect(c: c.item.render, for_each=op.tokens))
-            lit_token = {t: arg1 = \"bubble wrap\", render = t.arg1}
-            var_token = {t: arg1 = \"this\",
-                render = op.arg1.'reflective slot value'(t.arg1).show}
-            # XXX rewrite this without explicit recursion?
-            tokens = {t: ip = self.cursor # iter position
-                parse = prog.if(
-                    (t.ip.item == \"{\") -> t.parse_name,  # }
-                    else = t.parse_lit
-                )
-                cursor = t
-                item = t.parse.item
-                empty = t.ip.empty
-                advanced = op.tokens { ip = t.parse.ip }
-                parse_lit = {pl:
-                    pos = prog.sys.find(\"{\", in = t.ip)
-                    item = op.lit_token { \"\".join(pl.pos.before) }
-                    ip = pl.pos.after
-                }
-                next_char = t.ip.advanced.item
-                parse_name = prog.if(
-                    # special case for {{} and {}} (to represent literal { })
-                    ((t.next_char == \"{\") || (t.next_char == \"}\")) ->
-                        {lit: closer = t.ip.advanced.advanced  # {
-                            rv = prog.if((lit.closer.item == \"}\") -> {
-                                ip = lit.closer.advanced
-                                item = op.lit_token { t.next_char }
-                            }
-                            else = prog.error(\"faulty format\", \"\".join(t.ip)))
-                            ip = lit.rv.ip
-                            item = lit.rv.item
-                        }
-                    # normal case    
-                    else = {pn:  # {
-                        # XXX are we sure t.ip can't be empty??
-                        end = prog.sys.find(\"}\", in = t.ip.advanced)
-                        ip = prog.if(
-                            pn.end.after.empty.not -> pn.end.after.advanced
-                            else = prog.sys.nil
-                        )
-                        item = op.var_token { \"\".join(pn.end.before) }
-                    }
-                )
-            }
-        }
-    }
-find = {find: arg1 = \"x\", in = \"wxyz\"
-        if = find.arg1.'=='
-        cursor = find.in.cursor
-        advanced = find(cursor = find.cursor.advanced)
-        '()' = prog.if(
-            (find.cursor.empty || find.if(find.cursor.item)) -> {
-                after = find.cursor
-                before = prog.sys.nil
-            }
-            else = {
-                after = find.advanced.after
-                before = find.cursor.item @ find.advanced.before
-            }
-        )
-    }
-
-}}" ;;
-
hunk ./bicicleta_lib.ml 256
-    assert(lib_eval_is "(3.0**2).show" (UserString "9."));
+    assert(lib_eval_is "(3.0**2).show" (UserString "9.0"));
hunk ./prog.bicicleta 36
-        # One day, things will inherit from this implicitly if not 
-        # otherwise specified.
hunk ./prog.bicicleta 360
+        ln = self.new(self.intrinsics.float_ln)
+        exp = self.new(self.intrinsics.float_exp)
+        power = {op: arg1 = 2, '()' = (self.ln * op.arg1).exp}
}
