-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
16 changed files
with
333 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,10 @@ | ||
name = "Liang" | ||
uuid = "689e9e03-1340-4615-b78b-52f74a012268" | ||
authors = ["Roger-luo<[email protected]>",] | ||
authors = ["Roger-luo<[email protected]>"] | ||
version = "0.1.0" | ||
|
||
[deps] | ||
ExproniconLite = "55351af7-c7e9-48d6-89ff-24e801d99491" | ||
|
||
[compat] | ||
julia = "1.10" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,9 @@ | ||
module Liang | ||
|
||
# write your code here | ||
include("data/mod.jl") | ||
include("expr/mod.jl") | ||
include("rewrite/mod.jl") | ||
include("rules/mod.jl") | ||
include("target/mod.jl") | ||
|
||
end # Liang |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
Base.@kwdef struct SyntaxError <: Exception | ||
msg::String | ||
end | ||
|
||
function Base.showerror(io::IO, e::SyntaxError) | ||
print(io, e.msg) | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
# @data MyADT begin | ||
# Foo | ||
# Bar(Int, Float64) | ||
|
||
# struct Baz | ||
# x::Int | ||
# y::Float64 | ||
# z::Vector{MyADT} | ||
# end | ||
# end | ||
|
||
macro data(name::Symbol, expr) | ||
return esc(data_m(name, expr)) | ||
end | ||
|
||
function data_m(name::Symbol, expr) | ||
expr isa Expr || throw(SyntaxError("Expected an \ | ||
expression, got $(typeof(expr)): $expr")) | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
""" | ||
Provides the Algebraic Data Types (ADTs) for the project. | ||
""" | ||
module Data | ||
|
||
using ExproniconLite: JLKwField, JLKwStruct, rm_lineinfo, rm_nothing, no_default | ||
|
||
include("err.jl") | ||
include("macro.jl") | ||
include("syntax.jl") | ||
include("scan.jl") | ||
include("show.jl") | ||
|
||
|
||
end # Data |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
struct SizeInfo | ||
tag::Int | ||
bits::Int | ||
ptrs::Int | ||
end | ||
|
||
struct FieldInfo | ||
var::Symbol | ||
expr::Union{Symbol,Expr} | ||
is_bitstype::Bool | ||
type_guess # eval-ed type | ||
end | ||
|
||
struct VariantInfo | ||
def::Variant | ||
tag::UInt8 | ||
fields::Vector{FieldInfo} | ||
end | ||
|
||
struct EmitInfo | ||
def::TypeDef | ||
size::SizeInfo | ||
variants::Dict{Variant, VariantInfo} | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
struct FormatPrinter{IO_t, Indent, Leading, Print, PrintLn, Unquoted, Show, Sep} | ||
io::IO_t | ||
indent::Indent | ||
leading::Leading | ||
print::Print | ||
println::PrintLn | ||
unquoted::Unquoted | ||
show::Show | ||
sep::Sep | ||
end | ||
|
||
function FormatPrinter(io::IO) | ||
indent(n::Int) = Base.print(io, ' ' ^ n) | ||
leading() = indent(get(io, :indent, 0)) | ||
print(xs...; kw...) = Base.printstyled(io, xs...; kw...) | ||
println(xs...; kw...) = begin | ||
Base.printstyled(io, xs..., '\n'; kw...) | ||
leading() | ||
end | ||
print_unquoted(xs...; kw...) = print(Base.sprint(Base.show_unquoted, xs...); kw...) | ||
show(mime, x) = Base.show(io, mime, x) | ||
show(x) = Base.show(io, x) | ||
|
||
function sep(left, right, trim::Int = 20) | ||
_, width = displaysize(io) | ||
width = min(width, 80) | ||
nindent = get(io, :indent, 0) | ||
ncontent = textwidth(string(left)) - textwidth(string(right)) | ||
nsep = max(0, width - nindent - trim - ncontent) | ||
print(" ", "-"^nsep, " "; color=:light_black) | ||
end | ||
|
||
FormatPrinter(io, | ||
indent, leading, | ||
print, println, | ||
print_unquoted, | ||
show, sep | ||
) | ||
end | ||
|
||
function indent(f::FormatPrinter, n::Int = 4) | ||
FormatPrinter(IOContext(f.io, :indent=>get(f.io, :indent, 0) + n)) | ||
end | ||
|
||
function Base.show(io::IO, ::MIME"text/plain", var::TypeVar) | ||
isnothing(var.lower) || printstyled(io, var.lower, " <: "; color=:light_cyan) | ||
printstyled(io, var.name; color=:light_cyan) | ||
isnothing(var.upper) || printstyled(io, " <: ", var.upper; color=:light_cyan) | ||
end | ||
|
||
function Base.show(io::IO, ::MIME"text/plain", var::Variant) | ||
f = FormatPrinter(io) | ||
f.leading() | ||
isnothing(var.source) || f.println(var.source; color=:light_black) | ||
if var.kind === Named | ||
var.is_mutable && f.print("mutable "; color=:red) | ||
f.print("struct "; color=:red) | ||
f.print(var.name) | ||
|
||
ff = indent(f) | ||
for field in var.fields::Vector{NamedField} | ||
ff.println() | ||
isnothing(field.source) || (ff.println(field.source; color=:light_black)) | ||
ff.print(field.name) | ||
ff.print("::"; color=:red) | ||
ff.unquoted(field.type; color=:light_cyan) | ||
if field.default !== no_default | ||
ff.print(" = "; color=:red) | ||
ff.unquoted(field.default; color=:light_cyan) | ||
end | ||
end | ||
f.println() | ||
f.print("end"; color=:red) | ||
elseif var.kind === Anonymous | ||
f.print(var.name) | ||
f.print('('; color=:red) | ||
fields = var.fields::Vector{Field} | ||
if !isempty(fields) | ||
f.unquoted(fields[1].type; color=:light_cyan) | ||
for each in fields[2:end] | ||
f.print(", ") | ||
f.unquoted(each.type; color=:light_cyan) | ||
end | ||
end | ||
f.print(')'; color=:red) | ||
else # Singleton | ||
f.print(var.name) | ||
end | ||
end | ||
|
||
function Base.show(io::IO, mime::MIME"text/plain", def::TypeDef) | ||
f = FormatPrinter(io); f.leading() | ||
|
||
isnothing(def.source) || f.println(def.source; color=:light_black) | ||
f.print("@data "; color=:red) | ||
f.print(def.name) | ||
|
||
if !isnothing(def.supertype) | ||
f.print(" <: "; color=:red) | ||
f.unquoted(def.supertype; color=:light_cyan) | ||
end | ||
|
||
f.println(" begin"; color=:red) | ||
vf = indent(f) | ||
for (idx, each) in enumerate(def.variants) | ||
vf.show(mime, each) | ||
|
||
if idx < length(def.variants) | ||
vf.println() | ||
end | ||
end | ||
f.println() | ||
f.print("end"; color=:red) | ||
end # function Base.show |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
@enum VariantKind begin | ||
Singleton = 1 | ||
Anonymous = 2 | ||
Named = 3 | ||
end | ||
|
||
struct Field | ||
type::Union{Symbol,Expr} | ||
|
||
function Field(type::Union{Symbol,Expr}) | ||
type isa Symbol && return new(type) | ||
Meta.isexpr(type, :kw) && throw(SyntaxError("field type cannot be a keyword argument")) | ||
new(type) | ||
end | ||
end | ||
|
||
struct NamedField | ||
name::Symbol | ||
type::Union{Symbol,Expr} | ||
default # no_default, expr, or literal | ||
source::Union{Nothing,LineNumberNode} | ||
end | ||
|
||
function NamedField(f::JLKwField) | ||
NamedField(f.name, f.type, f.default, f.line) | ||
end | ||
|
||
struct Variant | ||
kind::VariantKind | ||
name::Symbol | ||
is_mutable::Bool | ||
fields::Union{Vector{Field},Vector{NamedField}} | ||
source::Union{Nothing,LineNumberNode} | ||
|
||
function Variant(kind, name, is_mutable, fields, source) | ||
if kind == Named | ||
all(fields) do f | ||
f isa NamedField | ||
end || throw(ArgumentError("fields must be a Vector{Field}")) | ||
elseif kind == Anonymous | ||
all(fields) do f | ||
f isa Field | ||
end || throw(ArgumentError("fields must be a Vector{NamedField}")) | ||
elseif kind == Singleton | ||
isnothing(fields) || isempty(fields) || throw(ArgumentError("fields must be nothing or empty")) | ||
else | ||
throw(ArgumentError("kind must be Named, Anonymous, or Singleton")) | ||
end | ||
|
||
name in fieldnames(DataType) && throw(SyntaxError("cannot use reserved name $name for variant", source)) | ||
name in (:data, :tag) && throw(SyntaxError("cannot use reserved name $name for variant", source)) | ||
|
||
new(kind, name, is_mutable, fields, source) | ||
end | ||
end | ||
|
||
struct TypeDef | ||
mod::Module | ||
name::Symbol | ||
supertype::Union{Nothing,Symbol,Expr} | ||
variants::Vector{Variant} | ||
source::Union{Nothing,LineNumberNode} | ||
end | ||
|
||
function Variant(ex::Union{Symbol, Expr}, source = nothing) | ||
if Meta.isexpr(ex, :struct) | ||
def = JLKwStruct(ex) | ||
def.ismutable && throw(SyntaxError("mutable structs are not supported"; source)) | ||
Variant(Named, def.name, def.ismutable, NamedField.(def.fields), source) | ||
elseif Meta.isexpr(ex, :call) | ||
ex.args[1] isa Symbol || throw(SyntaxError("variant name must be a symbol"; source)) | ||
Variant(Anonymous, ex.args[1], false, Field.(ex.args[2:end]), source) | ||
elseif ex isa Symbol | ||
Variant(Singleton, ex, false, Field[], source) | ||
else | ||
throw(SyntaxError("variant must be a struct, call, or symbol"; source)) | ||
end | ||
end | ||
|
||
function TypeDef(mod::Module, head, body::Expr; source=nothing) | ||
name, supertype = scan_data_head(head, source) | ||
variants = Variant[] | ||
let source = source | ||
for each in body.args | ||
each isa LineNumberNode && (source = each; continue) | ||
push!(variants, Variant(each, source)) | ||
end | ||
end # let | ||
|
||
length(variants) > 0 || throw(SyntaxError("type $name must have at least one variant"; source)) | ||
length(variants) > 256 && throw(SyntaxError("too many variants in type $name, 256 maximum"; source)) | ||
return TypeDef(mod, name, supertype, variants, source) | ||
end | ||
|
||
function scan_data_head(head, source=nothing) | ||
if Meta.isexpr(head, :<:) | ||
name, _ = scan_data_head(head.args[1]) | ||
supertype = head.args[2] | ||
elseif Meta.isexpr(head, :curly) | ||
throw(ArgumentError("type parameters are not allowed, we do not support generic ADTs yet")) | ||
elseif head isa Symbol | ||
name = head | ||
supertype = nothing | ||
else | ||
throw(ArgumentError("type name must be a symbol or curly expression")) | ||
end | ||
return name, supertype | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
""" | ||
Definition & Construction of Expressions | ||
""" | ||
module Expression | ||
|
||
|
||
end # Expression |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
""" | ||
The rewrite engine. | ||
""" | ||
module Rewrite | ||
end # Rewrite |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
""" | ||
Rewrite rules. | ||
""" | ||
module Rules | ||
end # Rules |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
""" | ||
Code generation targets. | ||
""" | ||
module Target | ||
end # Target |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
using Liang.Data: data_m | ||
|
||
data_m(:MyADT, :(Foo)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
module TestData | ||
end # TestData |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
using Liang.Data: TypeDef | ||
|
||
TypeDef(Main, :MyADT, quote | ||
Foo | ||
Bar(Int, Float64) | ||
|
||
struct Baz | ||
x::Int | ||
y::Float64 | ||
z::Vector{MyADT} | ||
end | ||
end) |