-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([resolve_indicators/1, compile/2, compile_from_strings/4]). -export_type([compilation_output/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())}. -file("src/caffeine_lang/compiler.gleam", 214). ?DOC( " Groups measured IRs by their resolved vendor, sorted by unique_identifier within each group.\n" " Only called with IRs that have a vendor (unmeasured IRs are filtered before this step).\n" ). -spec group_by_vendor( list(caffeine_lang@linker@ir:intermediate_representation(caffeine_lang@linker@ir:resolved())) ) -> gleam@dict:dict(caffeine_lang@analysis@vendor:vendor(), list(caffeine_lang@linker@ir:intermediate_representation(caffeine_lang@linker@ir:resolved()))). group_by_vendor(Irs) -> _pipe = gleam@list:group( Irs, fun(Ir) -> V@1 = case erlang:element(6, Ir) of {some, V} -> V; _assert_fail -> erlang:error(#{gleam_error => let_assert, message => <<"Pattern match failed, no pattern matched the value."/utf8>>, file => <>, module => <<"caffeine_lang/compiler"/utf8>>, function => <<"group_by_vendor"/utf8>>, line => 218, value => _assert_fail, start => 7657, 'end' => 7694, pattern_start => 7668, pattern_end => 7682}) end, V@1 end ), gleam@dict:map_values( _pipe, fun(_, Group) -> gleam@list:sort( Group, fun(A, B) -> gleam@string:compare( erlang:element(3, A), erlang:element(3, B) ) end ) end ). -file("src/caffeine_lang/compiler.gleam", 103). -spec run_code_generation( list(caffeine_lang@linker@ir:intermediate_representation(caffeine_lang@linker@ir:resolved())) ) -> {ok, compilation_output()} | {error, caffeine_lang@errors:compilation_error()}. run_code_generation(Resolved_irs) -> Measured_irs = gleam@list:filter( Resolved_irs, fun(Ir) -> gleam@option:is_some(erlang:element(6, Ir)) end ), Grouped = group_by_vendor(Measured_irs), Active_groups = begin _pipe = Grouped, _pipe@1 = maps:to_list(_pipe), gleam@list:map( _pipe@1, fun(Pair) -> {caffeine_lang@codegen@platforms:for_vendor( erlang:element(1, Pair) ), erlang:element(2, Pair)} end ) end, Active_groups@1 = case gleam@list:is_empty(Active_groups) of true -> [{caffeine_lang@codegen@platforms:for_vendor(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(8, Platform))(Irs), fun(_use0) -> {Vendor_resources, Vendor_warnings} = _use0, Settings = caffeine_lang@codegen@platforms:terraform_settings( Platform ), {ok, {lists:append(Resources, Vendor_resources), lists:append(Warnings, Vendor_warnings), lists:append( Req_provs, maps:to_list(erlang:element(3, Settings)) ), lists:append( Provs, [caffeine_lang@codegen@platforms:provider( Platform )] ), lists:append(Vars, erlang:element(7, 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@1) -> Base = terra_madre@common:sanitize_terraform_identifier( erlang:element(3, Ir@1) ), [{Base, erlang:element(2, Ir@1)}, {<>, erlang:element(2, Ir@1)}] 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@2) -> gleam@option:is_some( erlang:element(8, erlang:element(5, Ir@2)) ) 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", 94). ?DOC(false). -spec resolve_indicators( caffeine_lang@linker@ir:intermediate_representation(caffeine_lang@linker@ir:deps_validated()) ) -> {ok, caffeine_lang@linker@ir:intermediate_representation(caffeine_lang@linker@ir:resolved())} | {error, caffeine_lang@errors:compilation_error()}. resolve_indicators(Ir) -> case erlang:element(6, Ir) of {some, datadog} -> caffeine_lang@codegen@datadog:resolve_indicators(Ir); none -> {ok, caffeine_lang@linker@ir:promote(Ir)} end. -file("src/caffeine_lang/compiler.gleam", 80). -spec run_semantic_analysis( list(caffeine_lang@linker@ir:intermediate_representation(caffeine_lang@linker@ir:linked())) ) -> {ok, list(caffeine_lang@linker@ir:intermediate_representation(caffeine_lang@linker@ir:resolved()))} | {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) -> _pipe = Validated_irs, _pipe@1 = gleam@list:map(_pipe, fun resolve_indicators/1), caffeine_lang@errors:from_results(_pipe@1) end ). -file("src/caffeine_lang/compiler.gleam", 72). -spec run_parse_and_link( list(caffeine_lang@source_file:vendor_measurement_source()), list(caffeine_lang@source_file:source_file(caffeine_lang@source_file:expectation_source())) ) -> {ok, list(caffeine_lang@linker@ir:intermediate_representation(caffeine_lang@linker@ir:linked()))} | {error, caffeine_lang@errors:compilation_error()}. run_parse_and_link(Measurements, Expectations) -> Slo_params = caffeine_lang@standard_library@artifacts:slo_params(), caffeine_lang@linker@linker:link(Measurements, Expectations, Slo_params). -file("src/caffeine_lang/compiler.gleam", 42). ?DOC( " Compiles measurement sources and expectation sources into Terraform configuration.\n" " Pure function — all file reading happens before this function is called.\n" ). -spec compile( list(caffeine_lang@source_file:vendor_measurement_source()), list(caffeine_lang@source_file:source_file(caffeine_lang@source_file:expectation_source())) ) -> {ok, compilation_output()} | {error, caffeine_lang@errors:compilation_error()}. compile(Measurements, Expectations) -> gleam@result:'try'( run_parse_and_link(Measurements, 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", 228). -spec parse_from_strings(binary(), binary(), binary(), binary()) -> {ok, list(caffeine_lang@linker@ir:intermediate_representation(caffeine_lang@linker@ir:linked()))} | {error, caffeine_lang@errors:compilation_error()}. parse_from_strings( Measurements_source, Expectations_source, Expectations_path, Vendor_string ) -> Slo_params = caffeine_lang@standard_library@artifacts:slo_params(), Reserved_labels = caffeine_lang@linker@ir_builder:reserved_labels( Slo_params ), gleam@result:'try'( begin _pipe = caffeine_lang@analysis@vendor:resolve_vendor(Vendor_string), gleam@result:replace_error( _pipe, caffeine_lang@errors:linker_vendor_resolution_error( <<<<"unknown vendor '"/utf8, Vendor_string/binary>>/binary, "'"/utf8>> ) ) end, fun(Resolved_vendor) -> gleam@result:'try'( caffeine_lang@frontend@pipeline:compile_measurements( {source_file, <<"browser/measurements.caffeine"/utf8>>, Measurements_source} ), fun(Raw_measurements) -> 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@measurements:validate_measurements( Raw_measurements, Slo_params ), fun(Validated_measurements) -> Vendor_lookup = begin _pipe@1 = Raw_measurements, _pipe@2 = gleam@list:map( _pipe@1, fun(Bp) -> {erlang:element(2, Bp), Resolved_vendor} end ), maps:from_list(_pipe@2) end, gleam@result:'try'( caffeine_lang@linker@expectations:validate_expectations( Raw_expectations, Validated_measurements, Slo_params, Expectations_path ), fun(Expectations_measurement_collection) -> caffeine_lang@linker@ir_builder:build_all( [{Expectations_measurement_collection, Expectations_path}], Reserved_labels, Vendor_lookup, Slo_params ) end ) end ) end ) end ) end ). -file("src/caffeine_lang/compiler.gleam", 54). ?DOC( " Compiles from source strings directly (no file I/O).\n" " Used for browser-based compilation. The vendor parameter specifies\n" " which vendor the measurements belong to.\n" ). -spec compile_from_strings(binary(), binary(), binary(), binary()) -> {ok, compilation_output()} | {error, caffeine_lang@errors:compilation_error()}. compile_from_strings( Measurements_source, Expectations_source, Expectations_path, Vendor_string ) -> gleam@result:'try'( parse_from_strings( Measurements_source, Expectations_source, Expectations_path, Vendor_string ), fun(Irs) -> gleam@result:'try'( run_semantic_analysis(Irs), fun(Resolved_irs) -> run_code_generation(Resolved_irs) end ) end ).