Skip to content

Commit

Permalink
Continue Updating Claro Docs to Use Auto-Validated Examples
Browse files Browse the repository at this point in the history
  • Loading branch information
JasonSteving99 committed Feb 27, 2024
1 parent a0a20d9 commit bb67a3d
Show file tree
Hide file tree
Showing 14 changed files with 201 additions and 2 deletions.
1 change: 1 addition & 0 deletions mdbook_docs/src/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ write_source_file(
"//mdbook_docs/src/module_system/module_apis/type_definitions/initializers_and_unwrappers:initializers_and_unwrappers",
"//mdbook_docs/src/module_system/module_apis/type_definitions/initializers_and_unwrappers/unwrappers:unwrappers",
"//mdbook_docs/src/module_system/module_apis/type_definitions/opaque_types:opaque_types",
"//mdbook_docs/src/module_system/swapping_deps:swapping_deps",
"//mdbook_docs/src/module_system/visibility:visibility",
"//mdbook_docs/src/procedures/consumers:consumers",
"//mdbook_docs/src/procedures/functions:functions",
Expand Down
3 changes: 2 additions & 1 deletion mdbook_docs/src/SUMMARY.tmpl.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@
- [Flags](./module_system/module_apis/flags/flags.generated_docs.md)
- [HTTP Services](./module_system/module_apis/http_services/http_services.generated_docs.md)
- [Visibility](./module_system/visibility/visibility.generated_docs.md)
- [Swapping Dependencies](./module_system/swapping_deps/swapping_deps.generated_docs.md)
- [Concurrency](./concurrency.md)
- [Graph Procedures](./graph_procedures/graph_procedures.generated_docs.md)
- [Graph Procedure Composition](./graph_procedures/graph_procedure_composition/graph_procedure_composition.generated_docs.md)
Expand All @@ -102,7 +103,7 @@
- [Reusing Module APIs](./metaprogramming/code_reuse/reusing_module_apis/reusing_module_apis.generated_docs.md)
- [Reusing Source Code](./metaprogramming/code_reuse/reusing_source_code/reusing_source_code.generated_docs.md)
- [Abstract Modules](./metaprogramming/code_reuse/abstract_modules/abstract_modules.generated_docs.md)
- [Swapping Dependencies](./metaprogramming/swapping_deps/swapping_deps.generated_docs.md)
- [Configuring Dependencies with Build Flags](./metaprogramming/swapping_deps/swapping_deps.generated_docs.md)

---

Expand Down
7 changes: 7 additions & 0 deletions mdbook_docs/src/metaprogramming/swapping_deps/BUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
load("//mdbook_docs:docs_with_validated_examples.bzl", "doc_with_validated_examples")

doc_with_validated_examples(
name = "swapping_deps",
doc_template = "swapping_deps.tmpl.md",
examples = [],
)
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,6 @@ to be**
Whereas in other programming languages like Java or Python, you must consciously plan ahead in order to maintain
<a href="https://www.wikiwand.com/en/Loose_coupling" target="_blank">"loose coupling"</a> between program components.

This will be evaluated in more detail in following sections, but for now, we'll just take a moment to
This guarantee of loose coupling between Modules will be evaluated in more detail in a
[following section](../swapping_deps/swapping_deps.generated_docs.md), but for now, we'll just take a moment to
explicitly outline exactly what can be exported by a Module's API.
84 changes: 84 additions & 0 deletions mdbook_docs/src/module_system/swapping_deps/BUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
load("//:rules.bzl", "claro_binary", "claro_module")
load("//mdbook_docs:docs_with_validated_examples.bzl", "doc_with_validated_examples")

doc_with_validated_examples(
name = "swapping_deps",
doc_template = "swapping_deps.tmpl.md",
examples = [
{
"example": "get_message.claro_module_api",
"executable": False,
"codeblock_css_class": "claro",
},
{
"example": "modules_BULD",
"executable": False,
"codeblock_css_class": "python",
},
{
"example": "example.claro",
"append_output": False,
"deps": {"Msg": ":look_ma"},
},
{
"example": "binary_hello_BUILD",
"executable": False,
"codeblock_css_class": "python",
},
{
"example": ":hello_out",
"executable": False,
},
{
"example": "binary_look_ma_BUILD",
"executable": False,
"codeblock_css_class": "python",
},
{
"example": ":look_ma_out",
"executable": False,
},
{
"example": "extra_exports.claro_module_api",
"executable": False,
"codeblock_css_class": "claro",
},
],
)

claro_binary(
name = "test_hello",
main_file = "example.claro",
deps = {
"Msg": ":hello_world",
}
)
claro_binary(
name = "test_look_ma",
main_file = "example.claro",
deps = {
"Msg": ":look_ma",
}
)
claro_module(
name = "hello_world",
module_api_file = "get_message.claro_module_api",
srcs = ["hello_world.claro"],
)
claro_module(
name = "look_ma",
module_api_file = "get_message.claro_module_api",
srcs = ["look_ma.claro"],
)

[
genrule(
name = name + "_out",
outs = [name + "_out.txt"],
srcs = ["test_" + name + "_deploy.jar"],
cmd = "$(JAVA) -jar $(SRCS) > $(OUTS)",
tools = ["@bazel_tools//tools/jdk:current_java_runtime"],
toolchains = ["@bazel_tools//tools/jdk:current_java_runtime"],
)
for name in ["hello", "look_ma"]
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# BUILD
claro_binary(
name = "test",
main_file = "example.claro",
deps = {
"Msg": ":hello_world",
}
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# BUILD
claro_binary(
name = "test",
main_file = "example.claro",
deps = {
"Msg": ":look_ma", # Swapped for `:hello_world`.
}
)
2 changes: 2 additions & 0 deletions mdbook_docs/src/module_system/swapping_deps/example.claro
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# example.claro
print(Msg::getMessage());
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# extra_exports.claro_module_api
provider getMessage() -> string;

provider getMessageFromDB() -> future<string>;

opaque newtype SecretMessage

static SOME_OTHER_MESSAGE : SecretMessage;
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# get_message.claro_module_api
provider getMessage() -> string;
3 changes: 3 additions & 0 deletions mdbook_docs/src/module_system/swapping_deps/hello_world.claro
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
provider getMessage() -> string {
return "Hello, World!";
}
5 changes: 5 additions & 0 deletions mdbook_docs/src/module_system/swapping_deps/look_ma.claro
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
provider getMessage() -> string {
var msg = "Look ma, no hands!";
var line = strings::repeated("-", len(msg) + 4);
return "{line}\n| {msg} |\n{line}";
}
14 changes: 14 additions & 0 deletions mdbook_docs/src/module_system/swapping_deps/modules_BULD
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# BUILD
load("//:rules.bzl", "claro_binary", "claro_module")

claro_module(
name = "hello_world",
module_api_file = "get_message.claro_module_api",
srcs = ["hello_world.claro"],
)
claro_module(
name = "look_ma",
module_api_file = "get_message.claro_module_api",
srcs = ["look_ma.claro"],
)
# ...
55 changes: 55 additions & 0 deletions mdbook_docs/src/module_system/swapping_deps/swapping_deps.tmpl.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# Swapping Dependencies

Claro's Module system was very carefully designed to guarantee that it's **statically impossible for two separate
modules to be
<a href="https://www.wikiwand.com/en/Coupling_(computer_programming)#introduction" target="_blank">"tightly coupled"</a>**.
In this section we'll dive into exactly what that means.

As you've already seen in previous sections, Claro Modules explicitly declare a public API that indicates the full set
of procedures/values/Types that the Module's consumers will gain access to. Of course, some form of this is present in
every language. The unique distinction is that Claro Module dependencies can be directly swapped out to any other Module
with an appropriate API **without changing a single line of code in any `.claro` source files**.

For example, the below API...

{{EX1}}

...could be implemented by multiple Modules...

{{EX2}}

...and then the **exact same `.claro` source code**...

{{EX3}}

...could be compiled against either Module...

{{EX4}}
{{EX5}}

...and the behavior would depend on which dependency was chosen...

{{EX6}}
{{EX7}}

## Dep Validity is Based on Usage

The other subtle point that's likely easy to miss if it's not pointed out explicitly is that the validity of a Module
dependency is completely dependent upon the _usage_ of the dependency. In less opaque terms, this just means that a
Module dependency is valid if the Module's API actually exports everything that is _used_ by the consuming code. The
consuming code doesn't make any constraints on _anything other than what it actually uses_. So, a dependency can be
swapped for another that actually exports a _completely different_ API, so long as it **_at least_** exports everything
that the consuming code _actually used_ from the original Module's API.

For example, if a third Module actually implemented a totally different API such as:

{{EX8}}

the dependency would _still_ be valid because `example.claro` only actually _uses_ the `getMessage(...)` procedure that
is exported by both `:look_ma` and `:hello_world`.

This single design decision actually enables a huge amount of Build time configurability options. If you'd like to see
more about how you can take advantage of this, read about how you can swap dependencies programmatically using
[Build flags](../../metaprogramming/swapping_deps/swapping_deps.generated_docs.md). And if you're interested in becoming
a power-user, this feature can be leveraged in some very powerful ways via
[Build Time Metaprogramming](../../metaprogramming/metaprogramming.generated_docs.md).

0 comments on commit bb67a3d

Please sign in to comment.