Skip to content

Commit

Permalink
README
Browse files Browse the repository at this point in the history
  • Loading branch information
ehren committed Oct 31, 2024
1 parent 0c53e56 commit 21efd11
Showing 1 changed file with 38 additions and 11 deletions.
49 changes: 38 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ defmacro ([x, for (y in z)], x, y, z:
return quote([unquote(x), for (unquote(y) in unquote(z)), if (True)])
)

# metaprogramming in ceto/C++ templates rather than procedural macros is recommended:

def (maybe_reserve<T>, vec: mut:[T]:ref, sized: mut:auto:ref:ref:
vec.reserve(std.size(std.forward<decltype(sized)>(sized)))
) : void:requires:requires(std.size(sized))
Expand All @@ -68,50 +70,73 @@ include <map>

include (macros_list_comprehension)

# You can also do your metaprogramming by omitting the type annotations!
# Classes have immutable shared reference semantics by default
# (A class with generic data members is implicitly a C++ template class:
# - like an immutable by default Python 2 with good C++ interop/baggage and more parenthesese)

class (Foo:
data_member

def (method, param:
std.cout << param.size() << "\n"
return self
std.cout << param.size() << std.endl
return self # implicit +1 refcount (shared_from_this)
)

def (size:
return self.data_member.size()
)
)

def (calls_method, f:
return f.method(f)
# A non type-annotated ceto function is implicitly a sligtly more
# unconstrained/generic than default C++ template function
# (calls_method's arg is generic over all ceto class types and structs
# because "." is a maybe autoderef)

def (calls_method, arg:
return arg.method(arg)
)

# Unique classes are implicitly managed by std.unique_ptr and use cppfront inspired
# move from last use. Instance variables may be reassigned (allowing implicit move) but
# point to immutable instances (aka unique_ptr to const by default)

class (UniqueFoo:
consumed: [UniqueFoo] = []

def (size:
return self.consumed.size()
)

# For all classes and structs, a method that mutates its data members must be "mut".
# Note that "u" is a passed by value std::unique_ptr<const UniqueFoo> in C++
def (consuming_method: mut, u: UniqueFoo:

# u.consuming_method(None) # Compile time error:
# "u" is not a UniqueFoo:mut so a "mut" method call is illegal

# "u" is passed by reference to const to the generic method "method" here.
Foo(42).method(u)

# The last use of a :unique instance is std::move'd automatically.
# This is heavily inspired by the feature/idea in Herb Sutter's cppfront:
self.consumed.append(u)
self.consumed.append(u) # Ownership transfer of "u" on last use (implicit std.move)
)
) : unique

# std.string and vectors (implicit use of std.vector with square brackets) passed
# by reference to const by default:
def (string_join, vec: [std.string], sep = ", "s:
if (vec.empty():
return ""
)

# Explicit lambda capture brackets required for
# unsafe (potentially dangling) ref capture:
return std.accumulate(vec.cbegin() + 1, vec.cend(), vec[0],
lambda[&sep] (a, b, a + sep + b))
): std.string

# defmacro param types use the ast Node subclasses defined in selfhost/ast.cth

defmacro (s.join(v), s: StringLiteral, v:
return quote(string_join(unquote(v), unquote(s)))
)
Expand All @@ -122,7 +147,9 @@ def (main, argc: int, argv: const:char:ptr:const:ptr:
args = [std.string(a), for (a in std.span(argv, argc))]
summary = ", ".join(args)

f = Foo(summary) # in C++ f is a const std::shared_ptr<const Foo<decltype(summary)>>
f = Foo(summary) # implicit make_shared / extra CTAD:
# in C++ f is a const std::shared_ptr<const Foo<decltype(summary)>>

f.method(args) # autoderef of f
f.method(f) # autoderef also in the body of 'method'
calls_method(f) # autoderef in the body of calls_method (and method)
Expand All @@ -137,11 +164,11 @@ def (main, argc: int, argv: const:char:ptr:const:ptr:

std.cout << fut.get()

u: mut = UniqueFoo() # u is a (non-const) std::unique_ptr<"non-const" UniqueFoo> in C++
u2 = UniqueFoo() # u2 is a (non-const) std::unique_ptr<const UniqueFoo> in C++
u: mut = UniqueFoo() # u is a "non-const" std::unique_ptr<non-const UniqueFoo> in C++
u2 = UniqueFoo() # u2 is a non-const std::unique_ptr<const UniqueFoo> in C++

u.consuming_method(u2) # Implicit std.move from last use of u2.
# Note that :unique are non-const (allowing move) but
# :unique are non-const (allowing move) but
# unique_ptr-to-const by default.

u.consuming_method(u) # in C++: CETO_AUTODEREF(u).consuming_method(std::move(u))
Expand Down

0 comments on commit 21efd11

Please sign in to comment.