Skip to content

Commit

Permalink
Adding experimental SDML language support. (#862)
Browse files Browse the repository at this point in the history
* Adding experimental SDML language support.

[SDML](https://sdml.io) is a text-based modeling language using
tree-sitter with tools primarily in Rust. The goal is to advocate for
Topiary as *the* formatting tool for SDML source.

* Updated with comments from PR

1. Ran sdml.scm through topiary format.
2. Moved sdml from experimental to contributed in CLI.

* Updated with a more complete test case

This test samples covers about 85% of the formatter queries with only
some corners of the constraint language uncovered. Will update.

* Additional clean-up and test coverage for SDML

1. Test coverage >90% now.
2. Better support for multi-line cases especially for sequences.
3. Simplified a number of queries to reduce the number of top-level.

* Formatted sdml.scm correctly.

* 100% coverage for SDML formatter

* test: pass IO tests

* feat: cleanup changes

- remove comma from topiary-cli/Cargo.toml
- move line from experimental to contributed in README.md
- add PR description to CHANGELOG.md

* Update languages file with new repo hash

---------

Co-authored-by: Christopher Harrison <[email protected]>
  • Loading branch information
johnstonskj and Xophmeister authored Feb 21, 2025
1 parent 7dc784f commit 7950ba1
Show file tree
Hide file tree
Showing 12 changed files with 824 additions and 2 deletions.
4 changes: 2 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,9 @@ This name should be decided amongst the team before the release.

[Full list of changes](https://github.com/tweag/topiary/compare/v0.6.0...HEAD)


<!-- ### Added -->
### Added
<!-- - <New feature> -->
- [#862](https://github.com/tweag/topiary/pull/862) Added support for the Simple Domain Modeling Language ([SDML](https://sdml.io)), thanks to @johnstonskj

### Changed
<!-- - <Changes in existing functionality> -->
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ the same way as supported languages.

* [CSS] by @lavigneer
* [OpenSCAD] by @mkatychev
* [SDML] by @johnstonskj

#### Experimental

Expand Down Expand Up @@ -1847,6 +1848,7 @@ of choice open in another.
[prettier]: https://prettier.io/
[rust]: https://www.rust-lang.org
[rustfmt]: https://rust-lang.github.io/rustfmt
[sdml]: https://sdml.io/
[shfmt]: https://github.com/mvdan/sh
[toml]: https://toml.io
[topiary-playground]: https://topiary.tweag.io/playground
Expand Down
2 changes: 2 additions & 0 deletions topiary-cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ default = [
contributed = [
"css",
"openscad",
"sdml",
]

# Excluded by default
Expand All @@ -90,5 +91,6 @@ ocaml_interface = ["topiary-config/ocaml_interface", "topiary-queries/ocaml_inte
ocamllex = ["topiary-config/ocamllex", "topiary-queries/ocamllex"]
openscad = ["topiary-config/openscad", "topiary-queries/openscad"]
rust = ["topiary-config/rust", "topiary-queries/rust"]
sdml = ["topiary-config/sdml", "topiary-queries/sdml"]
toml = ["topiary-config/toml", "topiary-queries/toml"]
tree_sitter_query = ["topiary-config/tree_sitter_query", "topiary-queries/tree_sitter_query"]
3 changes: 3 additions & 0 deletions topiary-cli/src/io.rs
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,9 @@ where
#[cfg(feature = "rust")]
"rust" => Ok(topiary_queries::rust().into()),

#[cfg(feature = "sdml")]
"sdml" => Ok(topiary_queries::sdml().into()),

#[cfg(feature = "toml")]
"toml" => Ok(topiary_queries::toml().into()),

Expand Down
3 changes: 3 additions & 0 deletions topiary-cli/tests/sample-tester.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ fn get_file_extension(language: &str) -> &str {
"ocamllex" => "mll",
"openscad" => "scad",
"rust" => "rs",
"sdml" => "sdml",
"toml" => "toml",
"tree_sitter_query" => "scm",
_ => panic!("Invalid language input: {language}"),
Expand Down Expand Up @@ -86,6 +87,7 @@ mod test_fmt {
"ocamllex",
"openscad",
"rust",
"sdml",
"toml",
"tree_sitter_query",
fmt_input
Expand Down Expand Up @@ -164,6 +166,7 @@ mod test_coverage {
"ocamllex",
"openscad",
"rust",
"sdml",
"toml",
"tree_sitter_query",
coverage_input
Expand Down
196 changes: 196 additions & 0 deletions topiary-cli/tests/samples/expected/sdml.sdml
Original file line number Diff line number Diff line change
@@ -0,0 +1,196 @@
module sdml is
; Sample module for Topiary formatter.

import [ dc rdf skos xsd ]
import dc:issued as issued
import rdfs as schema
import [
magic
]

@dc:description = "A sample SDML module"
@issued = xsd:date("2025-02-06")

@magic:jpegFile = #[ ff d8 ff e0 ]

@magic:map = {unique} [
0 -> "zero"
1 -> "one"
2 -> "two"
;; ...
]

assert some_sequence_builder_silliness with
def map -> {ordered unique} (unsigned -> string)
:= [
0 -> "zero"
1 -> "one"
2 -> "two"
3 -> "three"
]
def odd_names -> {} string
:= {
name
|
forall pair in map, right(pair) = pair.left.is_odd
}
is
odd_names.length = 2
end

class Ordered is

def length -> unsigned

def drop (count → unsigned) → Self
def get (index → unsigned) → {0..1} Self

def reverse → Self

def slice (start → unsigned count → unsigned) → Self
:= take(drop(start) count) is
@dc:description = "return a slice of this list"
end

def take (count → unsigned) → Self is
assert count_subset is
count <= self.length
end
end

end

datatype Vin <- opaque string {
minLength = 12
maxLength = 16
} is
@dc:description = "an example"
end

datatype Money <- decimal {
fractionDigits = 3
totalDigits = 9
}

datatype Stars <- unsigned {
minInclusive = fixed 1
maxInclusive = fixed 5
}

datatype DateModified <- dateTime {
explicitTimezone = required
}

datatype uuid <- string {
pattern = [
"^(?:[[:xdigit:]]{32})$"
"^(?:[[:xdigit:]]{8}-[[:xdigit:]]{4}-[[:xdigit:]]{4}-[[:xdigit:]]{4}-[[:xdigit:]]{12})$"
"^(?:\\{[[:xdigit:]]{8}-[[:xdigit:]]{4}-[[:xdigit:]]{4}-[[:xdigit:]]{4}-[[:xdigit:]]{12}\\})$"
"^(?:\\([[:xdigit:]]{8}-[[:xdigit:]]{4}-[[:xdigit:]]{4}-[[:xdigit:]]{4}-[[:xdigit:]]{12}\\))$"
"^(?:\\{0x[[:xdigit:]]{8},(?:0x[[:xdigit:]]{4},){2}\\{(?:0x[[:xdigit:]]{2},){7}0x[[:xdigit:]]{2}\\}\\})$"
]
} is
@skos:prefLabel = "UUID"@en
@dc:description = "The string form of a UUID, conforming to one of 5 standard patterns."@en
end

dimension VehicleDimensions is
source Vehicle with [
vin
manufacturer
brand
model
modelYear
trim
color
tires
]
seatingRows -> unsigned
seatingCapacity -> unsigned
safetyRating -> unsigned
end

entity Vehicle is
@skos:prefLabel = [
"Vehicle"@en
""@fr
]
identity vin -> Vin
manufacturer -> Manufacturer
manufacturedLocation -> Location is
assert a_constant with
def const -> unsigned
:= 10
is
self /= const
end
end
manufacturedDate -> xds:date
brand -> Brand is
assert manufacturer_brand is
self.brand.manufacturer = self.manufacturer
end
end
model -> Model
modelYear -> xsd:gYear is
assert model_year_bounds is
self.modelYear >= 1910 and self.modelYear < now.year.plus_1
end
end
trim -> string is
assert model_trim is
exists t in self.model.trims, self.trim = t
end
end
color -> string
tires -> {ordered nonunique 0..} Tire
end

entity VehicleTitle is
identity number -> Sequence
ref vehicle
registeredOwner -> LegalPerson
ownerSince -> xsd:dateTime is
assert owned_after_made is
not self.ownerSince < self.vehicle.manufacturedDate
end
end
end

enum T_Shirt of
Small
Medium
Large
end
event VehicleTitleOwnerChanged is
source VehicleTitle with [ number vehicle registeredOwner ownerSince ]
end

event Foo is
source Bar with boo
end

property vehicle -> {1} Vehicle

property maybeVehicle -> {0..1} Vehicle

rdf Thing type schema:Class is
@dc:description = "?"
end

rdf Another type [ schema:Class Thing ] is
@dc:description = "??"
end

structure DateRange is
assert ends_after_starts = "end_date > start_date"
start_date -> xsd:date
end_date -> xsd:date
end

union ThisOrThat of
This
This as That
end

end
Loading

0 comments on commit 7950ba1

Please sign in to comment.