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 bf26150
Showing 1 changed file with 33 additions and 8 deletions.
41 changes: 33 additions & 8 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,71 @@ 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:
# - 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
return self # implicit +1 refcount (shared_from_this)
)

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

# Generic function == C++ template
# Note: calls_method is generic over ceto classes and structs (and external C++)
# because "." is a maybe autoderef

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

# 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 by default (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 ""
)

# potentially memory unsafe lambda captures require an explicit capture list:
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 +145,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 +162,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 bf26150

Please sign in to comment.