typecheck bits

Sophia bitstrings aren't really something you initialize manually, so we have to make up a literal format for them. Failing that, we just accept arbitrary integers and bytearrays as bitstrings.
This commit is contained in:
Jarvis Carroll 2026-02-13 06:22:07 +00:00
parent 9bc0ffafd1
commit 78c9c67f38

View File

@ -236,13 +236,13 @@ parse_expression(Type, Pos, String) ->
end.
parse_expression2(Type, Pos, String, {integer, _, Value, Row, Start, End}) ->
case Type of
{_, _, integer} ->
{ok, {Value, Pos, String}};
{_, _, unknown_type} ->
{ok, {Value, Pos, String}};
{O, N, _} ->
{error, {wrong_type, O, N, integer, Row, Start, End}}
typecheck_integer(Type, Pos, String, Value, Row, Start, End);
parse_expression2(Type, Pos, String, {character, "-", _, _, _, _}) ->
case next_token(Pos, String) of
{ok, {{integer, _, Value, Row, Start, End}, NewPos, NewString}} ->
typecheck_integer(Type, NewPos, NewString, -Value, Row, Start, End);
{error, Reason} ->
{error, Reason}
end;
parse_expression2(Type, Pos, String, {bytes, _, Value, Row, Start, End}) ->
Len = byte_size(Value),
@ -254,6 +254,10 @@ parse_expression2(Type, Pos, String, {bytes, _, Value, Row, Start, End}) ->
{ok, {Result, Pos, String}};
{_, _, {bytes, [ExpectedLen]}} ->
{error, {bytes_wrong_size, ExpectedLen, Len, Row, Start, End}};
{_, _, bits} ->
Size = bit_size(Value),
<<IntValue:Size>> = Value,
{ok, {{bits, IntValue}, Pos, String}};
{_, _, unknown_type} ->
{ok, {Result, Pos, String}};
{O, N, _} ->
@ -323,6 +327,10 @@ parse_alphanum(Type, Pos, String, ["true"], Row, Start, End) ->
typecheck_bool(Type, Pos, String, true, Row, Start, End);
parse_alphanum(Type, Pos, String, ["false"], Row, Start, End) ->
typecheck_bool(Type, Pos, String, false, Row, Start, End);
parse_alphanum(Type, Pos, String, ["Bits", "all"], Row, Start, End) ->
typecheck_bits(Type, Pos, String, -1, Row, Start, End);
parse_alphanum(Type, Pos, String, ["Bits", "none"], Row, Start, End) ->
typecheck_bits(Type, Pos, String, 0, Row, Start, End);
parse_alphanum(Type, Pos, String, [[C | _] = S], Row, Start, End) when ?IS_LATIN_LOWER(C) ->
% From a programming perspective, we are trying to parse a constant, so
% an alphanum token can really only be a constructor, or a chain object.
@ -350,6 +358,15 @@ parse_alphanum(Type, Pos, String, Path, Row, Start, End) ->
% must be a variant constructor, or invalid.
parse_variant(Type, Pos, String, Path, Row, Start, End).
typecheck_integer({_, _, integer}, Pos, String, Value, _, _, _) ->
{ok, {Value, Pos, String}};
typecheck_integer({_, _, unknown_type}, Pos, String, Value, _, _, _) ->
{ok, {Value, Pos, String}};
typecheck_integer({_, _, bits}, Pos, String, Value, _, _, _) ->
{ok, {{bits, Value}, Pos, String}};
typecheck_integer({O, N, _}, _, _, _, Row, Start, End) ->
{error, {wrong_type, O, N, integer, Row, Start, End}}.
typecheck_bool({_, _, unknown_type}, Pos, String, Value, _, _, _) ->
{ok, {Value, Pos, String}};
typecheck_bool({_, _, boolean}, Pos, String, Value, _, _, _) ->
@ -357,6 +374,13 @@ typecheck_bool({_, _, boolean}, Pos, String, Value, _, _, _) ->
typecheck_bool({O, N, _}, _, _, _, Row, Start, End) ->
{error, {wrong_type, O, N, boolean, Row, Start, End}}.
typecheck_bits({_, _, unknown_type}, Pos, String, Value, _, _, _) ->
{ok, {{bits, Value}, Pos, String}};
typecheck_bits({_, _, bits}, Pos, String, Value, _, _, _) ->
{ok, {{bits, Value}, Pos, String}};
typecheck_bits({O, N, _}, _, _, _, Row, Start, End) ->
{error, {wrong_type, O, N, bits, Row, Start, End}}.
typecheck_address({_, _, address}, Pos, String, Data, _, _, _) ->
{ok, {{address, Data}, Pos, String}};
typecheck_address({_, _, contract}, Pos, String, Data, _, _, _) ->
@ -939,6 +963,7 @@ anon_types_test() ->
% Integers.
check_parser("123"),
check_parser("1_2_3"),
check_parser("-123"),
% Booleans.
check_parser("true"),
check_parser("false"),
@ -1038,6 +1063,15 @@ chain_objects_test() ->
ok.
bits_test() ->
check_parser("Bits.all"),
check_parser("Bits.none"),
{_, Type} = compile_entrypoint_value_and_type("contract C = entrypoint f() = Bits.all", "f"),
check_sophia_to_fate(Type, "5", {bits, 5}),
check_sophia_to_fate(Type, "-5", {bits, -5}),
check_sophia_to_fate(Type, "#123", {bits, 256 + 32 + 3}),
ok.
singleton_records_test() ->
TypeDef = "record singleton('a) = {it: 'a}",
check_parser_with_typedef(TypeDef, "{it = 123}"),