Working on my language again, this time I'm starting with the actual execution model instead of starting with the types. Progress is going pretty good so far, haven't implemented any memory management (I've decided to patch the leaks later with GC lol), but I've got a bunch of expressions working and most of the type system after only about a week.
Here's the basic plan, the language's runtime form is an AST where every expression is a 2 tuple, the first element being the verb (function) and the second being the subject (argument) (I was pretty heavily inspired by Nock). One of the cool things I like about my design so far is that code is mixed with data seamlessly, and meta-programming becomes completely natural.
Example which culminates in
fib
Ruby:
TupleEvalInner = (Func t
(Eval # (Eval)uate evaulates the expression returned from Cond
((Cond (IsEmpty t)) # (Cond)ition returns a function that picks the first or second element of a tuple
[[] # Return empty tuple if empty (Tail returns empty if input is a 1-tuple or empty)
((Cat # Recursively con(Cat)enate the Eval of the tuple elements
(Eval (Head t)))
(TupleEvalInner (Tail t)))])))
TupleEval = (Func t # Elements of tuples are not implicity evaluated, so a function which does this is desirable
(Eval
((Cond (IsTuple t)) # Check that the input is a tuple
[(TupleEvalInner t) # Evaluate the tuple recursively
(Tup (Eval t))]))) # Or, Evaluate the value and put it in a 1-tuple
TupleApply = (Func f # With TupleEval, we can create a more typical multi-arg call function
(Func t
(f (TupleEval t)))) # Evaluate f against the evaulation of tuple t
Index = (Func i
(Func t # Produce a function which will index it's input by i
(Eval ((Cond
((TupleApply Eq) # Select the head if i is 0
[i 0]))
[(Head t)
((Index (Dec i)) # Recursively index with t = (Tail t) and i = (Dec i)
(Tail t))]))))
FibonnaciInner = (Func t
(Eval ((Cond
((TupleApply Eq) # Return t.1 if t.0 (the index) is equal to zero
[((Index 0) t) 0]))
[((Index 1) t)
((TupleApply FibonnaciInner) [
(Dec ((Index 0) t)) # Recursively call with t = [(t.0 - 1) (t.2) (t.2 + t.1)]
((Index 2) t)
((TupleApply Add) [
((Index 1) t)
((Index 2) t)])])])))
Fibonnaci = (Func i
((TupleApply FibonnaciInner)
[i 0 1]))
# General syntax
# Function invocation (all functions are unary)
(Func Value) => (Invoke [Func Value])
# Invocation with a Null function results in the argument
(Null Value) => Value
# The (Eval)uation of an (Expr)ession is the Eval of it's verb invoked on the Eval of it's subject
(Eval (Expr [Verb Subject]) => ((Eval Verb) (Eval Subject))
# An Eval of an Expr with Null verb results in the unevaluated subject
# (Used for edge cases where you want to pass an expression)
(Eval (Expr [Null Subject]) => Subject
# The Eval of a value results in the value itself
# Functions and Null are considered values for this purpose
(Eval Value) => Value
# Special syntax
# (Ex)pression denotes that the subject should return unevaluated
(Ex Subject) => (Eval (Expr [Null Subject]))
# Brackets denote a tuple, (Tup a) creates a 1-tuple with a
[a] => (Tup a)
# Cat concatinates the elements of two tuples
[a b...] => ((Cat [a]) [b...])
# Create a function with an argument and body
(Func arg body)
# Functions are kind of WIP at the moment, I'm not quite settled on their runtime form, while the other elements translate pretty much literally to the AST
Who would have thought that ruby syntax highlighting would be just about perfect for this?
Now you might ask if this means I've seen the light and become a fp weenie... No. Despite the appearances the language is largely imperative

Still a lot of work to do, but I feel like I'm making better progress than the last time I tried this. Ultimately I'm aiming for a mixed paradigm language that lets you be only as specific as you need to be, not quite duck-typed though, instead I'm hoping to have a interface/contract system that's not as restrictive and pedantic as OOP, but more specific than just looking up functions by name on a formless-mush-object.