envconf/generate.py

156 lines
4.5 KiB
Python
Executable File

#!/usr/bin/env python3
import typing
import tempfile
import os.path
import os
import shutil
import subprocess
from dataclasses import dataclass
@dataclass
class DataType:
const_type: str
go_type: str
sig_type: str
value_type: str
def get_return_type(levels: int, dtype: str) -> str:
return ("map[string]" * levels) + dtype
def get_signature(levels: int, data_type: DataType) -> str:
return (
"func (c *Config) Get"
+ ("Map" * levels)
+ data_type.sig_type
+ "(key string) (empty "
+ get_return_type(levels, data_type.go_type)
+ ") {"
)
def get_empty_def(levels: int, data_type: DataType) -> str:
return "empty = make(" + get_return_type(levels, data_type.go_type) + ")"
def get_nested_keys(levels: int) -> str:
txt = ""
for count in range(levels):
txt += "[k" + str(count + 11) + "]"
return txt
def get_retval_def(levels: int, current_level: int, data_type: DataType) -> str:
base = "retval := make("
if current_level > 0:
base = "retval" + get_nested_keys(current_level) + " = make("
return base + get_return_type(levels - current_level, data_type.go_type) + ")"
def get_entries(levels: int) -> str:
return f"v10, ok := c.mapEnv[{levels-1}].next[key]"
def get_entry(levels: int) -> str:
return f"entry := c.env[v{levels + 11}.key]"
def set_value(levels: int, data_type: DataType) -> str:
return f"retval{get_nested_keys(levels + 1)} = entry.parsed.{data_type.value_type}"
def get_loop(levels: int) -> str:
return f"for k{levels + 11}, v{levels + 11} := range v{levels + 10}.next {{"
def get_function(file: typing.TextIO, levels: int, data_type: DataType):
print(get_signature(levels, data_type), file=file)
print(get_empty_def(levels, data_type), file=file)
print(get_retval_def(levels, 0, data_type), file=file)
print("if c.parsed {", file=file)
print("key = cleanKey(key)", file=file)
print(get_entries(levels), file=file)
print("if ok {", file=file)
for level in range(levels - 1):
print(get_loop(level), file=file)
print(get_retval_def(levels, level + 1, data_type), file=file)
print(get_loop(levels - 1), file=file)
print(get_entry(levels - 1), file=file)
print(
f"if (entry.dtype.baseType() == {data_type.const_type}.baseType()) && (entry.parsed.err == nil) {{",
file=file,
)
print(set_value(levels - 1, data_type), file=file)
print("} else {", file=file)
print("return", file=file)
print("};" * (levels + 1), file=file)
print("return retval", file=file)
print("}", file=file)
print("}", file=file)
print("return", file=file)
print("}", file=file)
def main():
data_types = [
DataType(
const_type="TypeInt", go_type="int64", sig_type="Int", value_type="intval"
),
DataType(
const_type="TypeMetric",
go_type="int64",
sig_type="Metric",
value_type="intval",
),
DataType(
const_type="TypeDuration",
go_type="time.Duration",
sig_type="Duration",
value_type="durval",
),
DataType(
const_type="TypeString",
go_type="string",
sig_type="String",
value_type="strval",
),
DataType(
const_type="TypeDirectory",
go_type="string",
sig_type="Directory",
value_type="strval",
),
DataType(
const_type="TypeBool", go_type="bool", sig_type="Bool", value_type="boolval"
),
DataType(
const_type="TypeHex", go_type="[]byte", sig_type="Hex", value_type="binval"
),
]
levels = 5
with tempfile.TemporaryDirectory() as pathname:
code_file = os.path.join(pathname, "code.go")
with open(code_file, mode="w", encoding="utf-8") as f:
print("package envconf", file=f)
print('import "time"', file=f)
print(f"type mapEnvType [{levels}]*keyLookupType", file=f)
for level in range(levels):
for data_type in data_types:
get_function(f, level + 1, data_type)
if subprocess.run(["go", "fmt", code_file], check=True).returncode == 0:
shutil.copyfile(
code_file,
os.path.join(
os.path.dirname(os.path.realpath(__file__)), "auto_generated.go"
),
follow_symlinks=False,
)
if __name__ == "__main__":
main()