-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathRakefile
More file actions
148 lines (126 loc) · 4.04 KB
/
Rakefile
File metadata and controls
148 lines (126 loc) · 4.04 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
require 'active_support'
require 'know/ontology'
require 'rdf/turtle'
require 'stringio'
include ActiveSupport::Inflector, RDF
ActiveSupport::Inflector.inflections(:en) do |inflect|
inflect.irregular 'cafe', 'cafes'
end
task default: %w(codegen)
HEADER = <<~EOF
/* This is free and unencumbered software released into the public domain. */
#pragma once
EOF
file 'src/know/classes.hpp' => %w(../know.ttl) do |t|
ontology = Know::Ontology.load(t.prerequisites.first)
File.open(t.name, 'w') do |out|
out.puts HEADER
out.puts
ontology.classes.each do |klass|
out.puts %Q[#include "classes/#{klass.cpp_file}"]
end
end
end
task :codegen => %w(../know.ttl src/know/classes.hpp) do |t|
ontology = Know::Ontology.load(t.prerequisites.first)
ontology.classes.each do |klass|
filename = underscore(klass.name)
File.open("src/know/classes/#{filename}.hpp", 'w') do |out_file|
top, out = StringIO.new, StringIO.new
includes = {}
includes['cstdint'] = "for std::uint64_t"
includes['ctime'] = "for std::time_t" # TODO
includes['memory'] = "for std::shared_ptr"
includes['string'] = "for std::string"
includes['vector'] = "for std::vector"
# Generate the `know::$CLASS` class definition:
out.puts <<~EOF
class know::#{klass.cpp_name} {
using string = ::std::string;
template<typename T> using shared_ptr = ::std::shared_ptr<T>;
template<typename T> using vector = ::std::vector<T>;
public:
EOF
klass.properties.each do |property|
next if property.cpp_type.nil?
out.puts " #{property.cpp_type} #{property.cpp_name};"
end
out.puts unless klass.properties.empty?
out.puts " inline virtual ~#{klass.cpp_name}() = default;"
# Generate the `know::$CLASS#clone()` method:
out.puts
out.puts <<~EOF.lines.each { |s| s.prepend(' '*2) }.join
inline virtual shared_ptr<#{klass.cpp_name}> clone() const {
auto clone = std::make_shared<#{klass.cpp_name}>();
EOF
klass.properties.each do |property|
next if property.cpp_type.nil?
out.puts <<~EOF.lines.each { |s| s.prepend(' '*4) }.join
clone->#{property.cpp_name} = this->#{property.cpp_name};
EOF
end
out.puts <<~EOF.lines.each { |s| s.prepend(' '*2) }.join
return clone;
}
EOF
out.puts "};"
# Begin generating the file header:
top.puts HEADER
# Generate standard library dependencies:
top.puts unless includes.empty?
includes.each do |header, comment|
header = "<#{header}>"
top.puts "#include #{header.ljust(9)} // #{comment}"
end
# Generate internal dependencies:
top.puts unless klass.dependencies.empty?
klass.dependencies.each do |dependency|
top.puts "#include \"#{dependency.cpp_name}.hpp\""
end
top.puts
top.puts "namespace know {"
top.puts " class #{klass.cpp_name};"
klass.dependencies.each do |dependency|
top.puts " class #{dependency.cpp_name};"
end
top.puts "}"
top.puts
out_file.write top.string
out_file.write out.string
end
end
end
class Know::Ontology::Class
def cpp_file
"#{underscore(self.name.to_s)}.hpp"
end
def cpp_name
case self.name
when :Class then 'class_'
else underscore(self.name.to_s)
end
end
def cpp_type
"know::#{self.cpp_name}"
end
end
class Know::Ontology::Property
def cpp_name
name = underscore(self.name.to_s)
name = pluralize(name) unless self.functional?
name
end
def cpp_type
type = case type = self.range
when ::Know::Ontology::Class then "shared_ptr<know::#{type.cpp_name}>"
when ::XSD.anyURI then 'string'
when ::XSD.dateTime then 'std::time_t' # TODO
when ::XSD.language then 'string'
when ::XSD.nonNegativeInteger then 'std::uint64_t'
when ::XSD.string then 'string'
else return nil
end
type = "vector<#{type}>" unless self.functional?
type
end
end