checkpoint failing test after fixing tests checkpoint checkpoint checkpoint re-work asd checkpoint checkpoint checkpoint mix proj checkpoint mix first parser impl checkpoint fix tests re-org parser checkpoint strings fix multiline strings tuples checkpoint maps checkpoint checkpoint checkpoint checkpoint fix weird eof expression parse error checkpoint before typing checkpoint checpoint checkpoint checkpoint checkpoint ids in primitive types checkpoint checkpoint fix tests initial annotation checkpoint checkpoint checkpoint union subtyping conventions refactor - split typer typing tuples checkpoint test refactor checkpoint test refactor parsing atoms checkpoint atoms wip lists checkpoint typing lists checkopint checkpoint wip fixing correct list typing map discussion checkpoint map basic typing fix tests checkpoint checkpoint checkpoint checkpoint fix condition typing fix literal keys in map types checkpoint union types checkpoint union type checkpoint row types discussion & bidirectional typecheck checkpoint basic lambdas checkpoint lambdas typing application wip function application checkpoint checkpoint checkpoint cduce checkpoint checkpoint checkpoint checkpoint checkpoint checkpoint checkpoint
150 lines
5.5 KiB
Elixir
150 lines
5.5 KiB
Elixir
defmodule Til.ParseAtomTest do
|
|
use ExUnit.Case, async: true
|
|
|
|
alias Til.Parser
|
|
import Til.TestHelpers
|
|
|
|
describe "Atom parsing" do
|
|
test "parses a simple atom" do
|
|
source = ":hello"
|
|
{:ok, _nodes_map} = Parser.parse(source)
|
|
{atom_node, _map} = parse_and_get_first_node(source)
|
|
|
|
assert atom_node.ast_node_type == :literal_atom
|
|
assert atom_node.value == :hello
|
|
assert atom_node.raw_string == ":hello"
|
|
assert atom_node.location == [0, 1, 1, 6, 1, 7]
|
|
end
|
|
|
|
test "parses an atom with numbers and underscores" do
|
|
source = ":foo_123_bar"
|
|
{:ok, _nodes_map} = Parser.parse(source)
|
|
{atom_node, _map} = parse_and_get_first_node(source)
|
|
|
|
assert atom_node.ast_node_type == :literal_atom
|
|
assert atom_node.value == :foo_123_bar
|
|
assert atom_node.raw_string == ":foo_123_bar"
|
|
end
|
|
|
|
test "parses an atom within an s-expression" do
|
|
source = "(:an_atom)"
|
|
{:ok, nodes_map} = Parser.parse(source)
|
|
s_expr_node = get_first_child_node(nodes_map)
|
|
atom_node_id = hd(s_expr_node.children)
|
|
atom_node = get_node_by_id(nodes_map, atom_node_id)
|
|
|
|
assert atom_node.ast_node_type == :literal_atom
|
|
assert atom_node.value == :an_atom
|
|
assert atom_node.raw_string == ":an_atom"
|
|
# Location of :an_atom within ()
|
|
assert atom_node.location == [1, 1, 2, 9, 1, 10]
|
|
end
|
|
|
|
test "parses multiple atoms in an s-expression" do
|
|
source = "(:first :second)"
|
|
{:ok, nodes_map} = Parser.parse(source)
|
|
s_expr_node = get_first_child_node(nodes_map)
|
|
|
|
first_atom_node = get_node_by_id(nodes_map, Enum.at(s_expr_node.children, 0))
|
|
assert first_atom_node.ast_node_type == :literal_atom
|
|
assert first_atom_node.value == :first
|
|
assert first_atom_node.raw_string == ":first"
|
|
|
|
second_atom_node = get_node_by_id(nodes_map, Enum.at(s_expr_node.children, 1))
|
|
assert second_atom_node.ast_node_type == :literal_atom
|
|
assert second_atom_node.value == :second
|
|
assert second_atom_node.raw_string == ":second"
|
|
end
|
|
|
|
test "parses an atom followed immediately by an opening parenthesis (delimiter)" do
|
|
source = ":atom_name(foo)"
|
|
{:ok, nodes_map} = Parser.parse(source)
|
|
|
|
# First child of the file node should be the atom
|
|
atom_node = get_nth_child_node(nodes_map, 0)
|
|
assert atom_node.ast_node_type == :literal_atom
|
|
assert atom_node.value == :atom_name
|
|
assert atom_node.raw_string == ":atom_name"
|
|
assert atom_node.location == [0, 1, 1, 10, 1, 11]
|
|
|
|
# Second child should be the s-expression
|
|
s_expr_node = get_nth_child_node(nodes_map, 1)
|
|
assert s_expr_node.ast_node_type == :s_expression
|
|
assert s_expr_node.raw_string == "(foo)"
|
|
end
|
|
|
|
test "parses an atom at the end of input" do
|
|
source = " :last_atom "
|
|
{:ok, nodes_map} = Parser.parse(source)
|
|
# Use trimmed for helper
|
|
{atom_node, _map} = parse_and_get_first_node(String.trim(source))
|
|
|
|
assert atom_node.ast_node_type == :literal_atom
|
|
assert atom_node.value == :last_atom
|
|
assert atom_node.raw_string == ":last_atom"
|
|
# Location needs to be checked against the original source with whitespace
|
|
file_node = get_file_node_from_map(nodes_map)
|
|
actual_atom_node_id = hd(file_node.children)
|
|
actual_atom_node = get_node_by_id(nodes_map, actual_atom_node_id)
|
|
# " :last_atom "
|
|
assert actual_atom_node.location == [2, 1, 3, 12, 1, 13]
|
|
end
|
|
|
|
test "parses atom within a list expression" do
|
|
source = "[:my_list_atom]"
|
|
{:ok, nodes_map} = Parser.parse(source)
|
|
list_expr_node = get_first_child_node(nodes_map)
|
|
atom_node_id = hd(list_expr_node.children)
|
|
atom_node = get_node_by_id(nodes_map, atom_node_id)
|
|
|
|
assert atom_node.ast_node_type == :literal_atom
|
|
assert atom_node.value == :my_list_atom
|
|
assert atom_node.raw_string == ":my_list_atom"
|
|
end
|
|
|
|
test "parses atom within a tuple expression" do
|
|
source = "{:my_tuple_atom}"
|
|
{:ok, nodes_map} = Parser.parse(source)
|
|
tuple_expr_node = get_first_child_node(nodes_map)
|
|
atom_node_id = hd(tuple_expr_node.children)
|
|
atom_node = get_node_by_id(nodes_map, atom_node_id)
|
|
|
|
assert atom_node.ast_node_type == :literal_atom
|
|
assert atom_node.value == :my_tuple_atom
|
|
assert atom_node.raw_string == ":my_tuple_atom"
|
|
end
|
|
|
|
test "parses atom as a key in a map expression" do
|
|
source = "m{:key 1}"
|
|
{:ok, nodes_map} = Parser.parse(source)
|
|
map_expr_node = get_first_child_node(nodes_map)
|
|
|
|
key_node_id = Enum.at(map_expr_node.children, 0)
|
|
key_node = get_node_by_id(nodes_map, key_node_id)
|
|
|
|
assert key_node.ast_node_type == :literal_atom
|
|
assert key_node.value == :key
|
|
assert key_node.raw_string == ":key"
|
|
|
|
value_node_id = Enum.at(map_expr_node.children, 1)
|
|
value_node = get_node_by_id(nodes_map, value_node_id)
|
|
assert value_node.ast_node_type == :literal_integer
|
|
assert value_node.value == 1
|
|
end
|
|
|
|
test "parses atom as a value in a map expression" do
|
|
source = "m{'string_key' :atom_value}"
|
|
{:ok, nodes_map} = Parser.parse(source)
|
|
map_expr_node = get_first_child_node(nodes_map)
|
|
|
|
# string_key_node is child 0
|
|
value_node_id = Enum.at(map_expr_node.children, 1)
|
|
value_node = get_node_by_id(nodes_map, value_node_id)
|
|
|
|
assert value_node.ast_node_type == :literal_atom
|
|
assert value_node.value == :atom_value
|
|
assert value_node.raw_string == ":atom_value"
|
|
end
|
|
end
|
|
end
|