-module(caffeine_lang@compiler). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]). -define(FILEPATH, "src/caffeine_lang/compiler.gleam"). -export([compile/2, compile_from_strings/3]). -export_type([compilation_output/0, vendor_platform/0]). -if(?OTP_RELEASE >= 27). -define(MODULEDOC(Str), -moduledoc(Str)). -define(DOC(Str), -doc(Str)). -else. -define(MODULEDOC(Str), -compile([])). -define(DOC(Str), -compile([])). -endif. -type compilation_output() :: {compilation_output, binary(), gleam@option:option(binary()), list(binary())}. -type vendor_platform() :: {vendor_platform, caffeine_lang@analysis@vendor:vendor(), fun((list(caffeine_lang@linker@ir:intermediate_representation())) -> {ok, {list(terra_madre@terraform:resource()), list(binary())}} | {error, caffeine_lang@errors:compilation_error()}), terra_madre@terraform:terraform_settings(), terra_madre@terraform:provider(), list(terra_madre@terraform:variable())}. -file("src/caffeine_lang/compiler.gleam", 67). -spec run_parse_and_link( caffeine_lang@source_file:source_file(), list(caffeine_lang@source_file:source_file()) ) -> {ok, list(caffeine_lang@linker@ir:intermediate_representation())} | {error, caffeine_lang@errors:compilation_error()}. run_parse_and_link(Blueprint, Expectations) -> caffeine_lang@linker@linker:link(Blueprint, Expectations). -file("src/caffeine_lang/compiler.gleam", 74). -spec run_semantic_analysis( list(caffeine_lang@linker@ir:intermediate_representation()) ) -> {ok, list(caffeine_lang@linker@ir:intermediate_representation())} | {error, caffeine_lang@errors:compilation_error()}. run_semantic_analysis(Irs) -> gleam@result:'try'( caffeine_lang@analysis@dependency_validator:validate_dependency_relations( Irs ), fun(Validated_irs) -> caffeine_lang@analysis@semantic_analyzer:resolve_intermediate_representations( Validated_irs ) end ). -file("src/caffeine_lang/compiler.gleam", 97). ?DOC(" Returns the platform configuration for a given vendor.\n"). -spec platform_for(caffeine_lang@analysis@vendor:vendor()) -> vendor_platform(). platform_for(V) -> case V of datadog -> {vendor_platform, datadog, fun caffeine_lang@codegen@datadog:generate_resources/1, caffeine_lang@codegen@datadog:terraform_settings(), caffeine_lang@codegen@datadog:provider(), caffeine_lang@codegen@datadog:variables()}; honeycomb -> {vendor_platform, honeycomb, fun(Irs) -> _pipe = caffeine_lang@codegen@honeycomb:generate_resources( Irs ), gleam@result:map(_pipe, fun(R) -> {R, []} end) end, caffeine_lang@codegen@honeycomb:terraform_settings(), caffeine_lang@codegen@honeycomb:provider(), caffeine_lang@codegen@honeycomb:variables()}; dynatrace -> {vendor_platform, dynatrace, fun(Irs@1) -> _pipe@1 = caffeine_lang@codegen@dynatrace:generate_resources( Irs@1 ), gleam@result:map(_pipe@1, fun(R@1) -> {R@1, []} end) end, caffeine_lang@codegen@dynatrace:terraform_settings(), caffeine_lang@codegen@dynatrace:provider(), caffeine_lang@codegen@dynatrace:variables()}; new_relic -> {vendor_platform, new_relic, fun(Irs@2) -> _pipe@2 = caffeine_lang@codegen@newrelic:generate_resources( Irs@2 ), gleam@result:map(_pipe@2, fun(R@2) -> {R@2, []} end) end, caffeine_lang@codegen@newrelic:terraform_settings(), caffeine_lang@codegen@newrelic:provider(), caffeine_lang@codegen@newrelic:variables()} end. -file("src/caffeine_lang/compiler.gleam", 253). ?DOC(" Groups IRs by their resolved vendor, preserving input order within each group.\n"). -spec group_by_vendor( list(caffeine_lang@linker@ir:intermediate_representation()) ) -> gleam@dict:dict(caffeine_lang@analysis@vendor:vendor(), list(caffeine_lang@linker@ir:intermediate_representation())). group_by_vendor(Irs) -> _pipe = gleam@list:group(Irs, fun(Ir) -> case erlang:element(7, Ir) of {some, V} -> V; none -> datadog end end), gleam@dict:map_values(_pipe, fun(_, Group) -> lists:reverse(Group) end). -file("src/caffeine_lang/compiler.gleam", 143). -spec run_code_generation( list(caffeine_lang@linker@ir:intermediate_representation()) ) -> {ok, compilation_output()} | {error, caffeine_lang@errors:compilation_error()}. run_code_generation(Resolved_irs) -> Grouped = group_by_vendor(Resolved_irs), Active_groups = begin _pipe = Grouped, _pipe@1 = maps:to_list(_pipe), gleam@list:map( _pipe@1, fun(Pair) -> {platform_for(erlang:element(1, Pair)), erlang:element(2, Pair)} end ) end, Active_groups@1 = case gleam@list:is_empty(Active_groups) of true -> [{platform_for(datadog), []}]; false -> Active_groups end, gleam@result:'try'( gleam@list:try_fold( Active_groups@1, {[], [], [], [], []}, fun(Acc, Group) -> {Platform, Irs} = Group, {Resources, Warnings, Req_provs, Provs, Vars} = Acc, gleam@result:'try'( (erlang:element(3, Platform))(Irs), fun(_use0) -> {Vendor_resources, Vendor_warnings} = _use0, {ok, {lists:append(Resources, Vendor_resources), lists:append(Warnings, Vendor_warnings), lists:append( Req_provs, maps:to_list( erlang:element( 3, erlang:element(4, Platform) ) ) ), lists:append( Provs, [erlang:element(5, Platform)] ), lists:append(Vars, erlang:element(6, Platform))}} end ) end ), fun(_use0@1) -> {All_resources, All_warnings, Required_providers, Providers, Variables} = _use0@1, Terraform_settings = {terraform_settings, none, maps:from_list(Required_providers), none, none}, Boilerplate_config = {config, {some, Terraform_settings}, Providers, [], [], Variables, [], [], []}, Boilerplate = terra_madre@render:render_config(Boilerplate_config), Metadata_by_name = begin _pipe@2 = Resolved_irs, _pipe@3 = gleam@list:flat_map( _pipe@2, fun(Ir) -> Base = terra_madre@common:sanitize_terraform_identifier( erlang:element(3, Ir) ), [{Base, erlang:element(2, Ir)}, {<>, erlang:element(2, Ir)}] end ), maps:from_list(_pipe@3) end, Resource_sections = begin _pipe@4 = All_resources, gleam@list:map( _pipe@4, fun(Resource) -> Rendered = caffeine_lang@codegen@generator_utils:render_resource_to_string( Resource ), case gleam_stdlib:map_get( Metadata_by_name, erlang:element(3, Resource) ) of {ok, Metadata} -> <<<<(caffeine_lang@codegen@generator_utils:build_source_comment( Metadata ))/binary, "\n"/utf8>>/binary, Rendered/binary>>; {error, _} -> Rendered end end ) end, Terraform_output = case Resource_sections of [] -> Boilerplate; Sections -> Trimmed_boilerplate = gleam@string:drop_end(Boilerplate, 1), <<<<<>/binary, (gleam@string:join(Sections, <<"\n\n"/utf8>>))/binary>>/binary, "\n"/utf8>> end, Has_deps = begin _pipe@5 = Resolved_irs, gleam@list:any( _pipe@5, fun(Ir@1) -> gleam@list:contains( erlang:element(4, Ir@1), dependency_relations ) end ) end, Graph = case Has_deps of true -> {some, caffeine_lang@codegen@dependency_graph:generate( Resolved_irs )}; false -> none end, {ok, {compilation_output, Terraform_output, Graph, All_warnings}} end ). -file("src/caffeine_lang/compiler.gleam", 40). ?DOC( " Compiles a blueprint and expectation sources into Terraform configuration.\n" " Pure function — all file reading happens before this function is called.\n" ). -spec compile( caffeine_lang@source_file:source_file(), list(caffeine_lang@source_file:source_file()) ) -> {ok, compilation_output()} | {error, caffeine_lang@errors:compilation_error()}. compile(Blueprint, Expectations) -> gleam@result:'try'( run_parse_and_link(Blueprint, Expectations), fun(Irs) -> gleam@result:'try'( run_semantic_analysis(Irs), fun(Resolved_irs) -> run_code_generation(Resolved_irs) end ) end ). -file("src/caffeine_lang/compiler.gleam", 266). -spec parse_from_strings(binary(), binary(), binary()) -> {ok, list(caffeine_lang@linker@ir:intermediate_representation())} | {error, caffeine_lang@errors:compilation_error()}. parse_from_strings(Blueprints_source, Expectations_source, Expectations_path) -> Artifacts = caffeine_lang@standard_library@artifacts:standard_library(), Reserved_labels = caffeine_lang@linker@ir_builder:reserved_labels_from_artifacts( Artifacts ), gleam@result:'try'( caffeine_lang@frontend@pipeline:compile_blueprints( {source_file, <<"browser/blueprints.caffeine"/utf8>>, Blueprints_source} ), fun(Raw_blueprints) -> gleam@result:'try'( caffeine_lang@frontend@pipeline:compile_expects( {source_file, <<"browser/expectations.caffeine"/utf8>>, Expectations_source} ), fun(Raw_expectations) -> gleam@result:'try'( caffeine_lang@linker@blueprints:validate_blueprints( Raw_blueprints, Artifacts ), fun(Validated_blueprints) -> gleam@result:'try'( caffeine_lang@linker@expectations:validate_expectations( Raw_expectations, Validated_blueprints, Expectations_path ), fun(Expectations_blueprint_collection) -> caffeine_lang@linker@ir_builder:build_all( [{Expectations_blueprint_collection, Expectations_path}], Reserved_labels ) end ) end ) end ) end ). -file("src/caffeine_lang/compiler.gleam", 51). ?DOC( " Compiles from source strings directly (no file I/O).\n" " Used for browser-based compilation.\n" ). -spec compile_from_strings(binary(), binary(), binary()) -> {ok, compilation_output()} | {error, caffeine_lang@errors:compilation_error()}. compile_from_strings(Blueprints_source, Expectations_source, Expectations_path) -> gleam@result:'try'( parse_from_strings( Blueprints_source, Expectations_source, Expectations_path ), fun(Irs) -> gleam@result:'try'( run_semantic_analysis(Irs), fun(Resolved_irs) -> run_code_generation(Resolved_irs) end ) end ).