提交 92951e89 编写于 作者: O openeuler-ci-bot 提交者: Gitee

!106 add generate command, which can generate the tuning project yaml depend on rules

Merge pull request !106 from lixiaoguang/dev_generation
......@@ -41,6 +41,7 @@ install:
rm -rf $(DESTDIR)/var/lib/atuned/
rm -rf $(DESTDIR)/var/run/atuned/
mkdir -p $(DESTDIR)/etc/atuned/tuning
mkdir -p $(DESTDIR)/etc/atuned/rules
mkdir -p $(DESTDIR)/etc/atuned/training
mkdir -p $(DESTDIR)/etc/atuned/classification
mkdir -p $(DESTDIR)$(PREFIX)/lib/atuned/modules
......@@ -57,6 +58,7 @@ install:
install -m 750 pkg/atuned $(BINDIR)
install -m 640 misc/atuned.service $(SYSTEMDDIR)
install -m 640 misc/atuned.cnf $(DESTDIR)/etc/atuned/
install -m 640 rules/tuning/tuning_rules.grl $(DESTDIR)/etc/atuned/rules
install -m 640 misc/atune-engine.service $(SYSTEMDDIR)
install -m 640 database/atuned.db $(DESTDIR)/var/lib/atuned/
install -m 640 misc/atune-adm $(DESTDIR)$(PREFIX)/share/bash-completion/completions/
......
......@@ -78,6 +78,10 @@ class Collector(Resource):
float_data.append(type_name)
data.append(float_data)
data_average = [sum(elem)/len(elem) for elem in zip(*data)]
data_result = {}
for index, _ in enumerate(data_average):
data_result[field_name[index]] = data_average[index]
if n_pipe is not None:
n_pipe.close()
......@@ -85,6 +89,7 @@ class Collector(Resource):
save_file(path, data, field_name)
result = {}
result["path"] = path
result["data"] = data_result
return result, 200
......
......@@ -8,8 +8,6 @@ import (
fmt "fmt"
proto "github.com/golang/protobuf/proto"
grpc "google.golang.org/grpc"
codes "google.golang.org/grpc/codes"
status "google.golang.org/grpc/status"
math "math"
)
......@@ -590,51 +588,52 @@ func init() {
func init() { proto.RegisterFile("profile.proto", fileDescriptor_744bf7a47b381504) }
var fileDescriptor_744bf7a47b381504 = []byte{
// 702 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x55, 0x5d, 0x4f, 0xdb, 0x3c,
0x14, 0x26, 0x29, 0xb4, 0xe5, 0xb4, 0x50, 0x5e, 0x8b, 0x17, 0x45, 0x68, 0x9b, 0x50, 0xae, 0xb8,
0x42, 0x68, 0x93, 0xf6, 0xa1, 0x0a, 0xa6, 0xac, 0x68, 0x52, 0x27, 0x60, 0xa8, 0x2d, 0x1a, 0xb7,
0x26, 0x31, 0xa9, 0x15, 0x37, 0x8e, 0x1c, 0x97, 0x89, 0xfd, 0x93, 0xfd, 0x9b, 0xdd, 0xec, 0x7f,
0x4d, 0x76, 0xec, 0x34, 0xad, 0xda, 0x69, 0xf4, 0x2e, 0xcf, 0xe3, 0xf3, 0x1c, 0x1f, 0x9f, 0xaf,
0xc0, 0x4e, 0x26, 0xf8, 0x03, 0x65, 0xe4, 0x24, 0x13, 0x5c, 0x72, 0xd4, 0x30, 0xd0, 0x9f, 0x40,
0xeb, 0x92, 0xe6, 0xf2, 0x8a, 0xe4, 0x39, 0x8e, 0x09, 0xf2, 0xa1, 0xfd, 0x8d, 0x8b, 0x84, 0x71,
0x1c, 0x8d, 0x9e, 0x32, 0xe2, 0x39, 0x47, 0xce, 0xf1, 0xf6, 0x60, 0x8e, 0x53, 0x36, 0x37, 0x85,
0xfa, 0x1a, 0x4f, 0x48, 0xee, 0xb9, 0x85, 0x4d, 0x95, 0x43, 0x07, 0x50, 0x0f, 0x42, 0x49, 0x1f,
0x89, 0x57, 0xd3, 0xa7, 0x06, 0xf9, 0x5d, 0x68, 0x19, 0xbb, 0x7e, 0xfa, 0xc0, 0x11, 0x82, 0x4d,
0x65, 0x6f, 0xae, 0xd1, 0xdf, 0xc8, 0x83, 0x46, 0x8f, 0xa7, 0x92, 0xa4, 0x52, 0x7b, 0x6e, 0x0f,
0x2c, 0xf4, 0xbb, 0xd0, 0x09, 0x52, 0xcc, 0x9e, 0x72, 0x9a, 0xdb, 0x78, 0x97, 0x39, 0xd8, 0x87,
0xad, 0x2b, 0x1e, 0x11, 0x66, 0x02, 0x2b, 0x80, 0xff, 0x12, 0x6a, 0x41, 0x98, 0xa8, 0xc0, 0x86,
0x12, 0xcb, 0x69, 0x6e, 0x24, 0x06, 0xf9, 0x77, 0xd0, 0x0c, 0xc2, 0xa4, 0x37, 0x26, 0x61, 0xb2,
0xd4, 0xe9, 0x4c, 0xe7, 0x56, 0x75, 0xe8, 0x08, 0x5a, 0x17, 0x24, 0x0f, 0x05, 0xcd, 0x24, 0xe5,
0xa9, 0x79, 0x6d, 0x95, 0xf2, 0xef, 0x00, 0xcc, 0x93, 0x2f, 0x79, 0x8c, 0x76, 0xc1, 0xed, 0x47,
0xda, 0x73, 0x6d, 0xe0, 0xf6, 0x23, 0xf4, 0x02, 0xb6, 0x6d, 0x42, 0x22, 0xe3, 0x7a, 0x46, 0xa8,
0xd3, 0x11, 0x9d, 0x90, 0x5c, 0xe2, 0x49, 0x66, 0x7c, 0xcf, 0x08, 0xff, 0xb7, 0x03, 0xad, 0x1e,
0x67, 0x8c, 0x84, 0xf2, 0x33, 0xc3, 0x31, 0x3a, 0x84, 0x66, 0x3f, 0x95, 0x44, 0x3c, 0x62, 0x66,
0x6e, 0x28, 0xb1, 0x3a, 0xbb, 0x98, 0x0a, 0xac, 0x83, 0x74, 0x8b, 0x33, 0x8b, 0xd5, 0x99, 0x2d,
0xb0, 0xb9, 0xa4, 0xc4, 0xe8, 0x15, 0xc0, 0xd7, 0xa9, 0xcc, 0xa6, 0xf2, 0x06, 0xcb, 0xb1, 0xb7,
0xa9, 0x4f, 0x2b, 0x8c, 0x4a, 0xf6, 0x27, 0xc6, 0xc3, 0xc4, 0xdb, 0x2a, 0x92, 0xad, 0x81, 0xaa,
0xe1, 0x35, 0x91, 0xdf, 0xb9, 0x48, 0xbc, 0xba, 0xe6, 0x2d, 0x54, 0xb9, 0xd5, 0x8d, 0xd5, 0x28,
0x72, 0xab, 0xbe, 0xfd, 0x2f, 0xd0, 0x1e, 0x09, 0x4c, 0x53, 0x5b, 0x54, 0x15, 0x2b, 0x96, 0x58,
0xdf, 0x58, 0xd4, 0xa0, 0xc4, 0x0b, 0xf1, 0xb8, 0x8b, 0xf1, 0xf8, 0x3f, 0x1d, 0xd8, 0xb9, 0x20,
0x0f, 0x34, 0x25, 0xd6, 0xdb, 0x11, 0xb4, 0x86, 0x44, 0x3c, 0xd2, 0x90, 0x54, 0x3a, 0xba, 0x4a,
0xa1, 0x63, 0xe8, 0x04, 0x59, 0xc6, 0x68, 0xa8, 0xd3, 0xa1, 0x4b, 0x5f, 0x38, 0x5e, 0xa4, 0x55,
0xeb, 0x0f, 0x43, 0x92, 0x62, 0x41, 0xb9, 0x36, 0x2b, 0xb2, 0x35, 0xc7, 0x55, 0xfb, 0x77, 0x73,
0xbe, 0x7f, 0x87, 0xd0, 0x19, 0x86, 0x63, 0x12, 0x4d, 0x59, 0x19, 0xdc, 0x1e, 0xd4, 0x82, 0x2c,
0x33, 0x41, 0xa9, 0xcf, 0x32, 0x41, 0xee, 0x2c, 0x41, 0x2a, 0x21, 0x43, 0x29, 0xb0, 0x24, 0xf1,
0x93, 0x2d, 0x90, 0xc5, 0xaf, 0x7f, 0x35, 0xca, 0xfe, 0xba, 0x8a, 0x05, 0x7a, 0x0b, 0x0d, 0x83,
0xd0, 0xfe, 0x89, 0x9d, 0xf9, 0xca, 0xc8, 0x1d, 0xfe, 0x57, 0xb2, 0xb6, 0xdf, 0xfd, 0x8d, 0x53,
0x07, 0x7d, 0x84, 0x3d, 0x0d, 0xfa, 0x29, 0x95, 0x6b, 0x39, 0xe8, 0x42, 0xd3, 0x0e, 0x27, 0xf2,
0x66, 0x26, 0xf3, 0xf3, 0xba, 0x4a, 0xfc, 0x0e, 0xea, 0xa3, 0x69, 0x4a, 0xd3, 0xf8, 0x19, 0x77,
0x1e, 0x3b, 0xa7, 0x0e, 0x3a, 0x87, 0xb6, 0x5a, 0x5f, 0x65, 0xbb, 0x2e, 0x97, 0xcf, 0xd8, 0xca,
0xae, 0xd3, 0x17, 0x9f, 0xc1, 0xee, 0x6d, 0x16, 0x0b, 0x1c, 0x91, 0xb5, 0x1e, 0x7d, 0x06, 0x2d,
0x75, 0xfc, 0x77, 0xed, 0x52, 0x56, 0xcb, 0x03, 0x40, 0xda, 0x57, 0xb1, 0x1c, 0xd7, 0x8a, 0xe0,
0x1c, 0x3a, 0xc6, 0x6a, 0xc0, 0x19, 0xbb, 0xc7, 0x61, 0xf2, 0x6c, 0x7d, 0x6f, 0x8c, 0x55, 0x2f,
0x09, 0xfa, 0xa3, 0x58, 0x07, 0xcf, 0xd2, 0x7f, 0x00, 0x30, 0x2b, 0x68, 0x5e, 0x5a, 0xd9, 0x4b,
0xab, 0xa4, 0xef, 0xa1, 0xa9, 0xc7, 0x5e, 0x95, 0xfd, 0xff, 0xd2, 0xa4, 0xba, 0x09, 0x56, 0x29,
0x4f, 0xa1, 0x5e, 0xcc, 0x38, 0x3a, 0x28, 0x0d, 0xe6, 0x86, 0xfe, 0xb0, 0x5d, 0x15, 0xfa, 0x1b,
0xe8, 0x44, 0x29, 0x18, 0x91, 0xab, 0xb2, 0xbb, 0xc4, 0xfe, 0x36, 0x8b, 0xf0, 0x3f, 0xdb, 0x77,
0xa1, 0x69, 0x47, 0xbb, 0xd2, 0xfd, 0x0b, 0xd3, 0xbe, 0xe2, 0x39, 0xf7, 0x75, 0xfd, 0x4f, 0x7e,
0xf3, 0x27, 0x00, 0x00, 0xff, 0xff, 0xf1, 0x88, 0xa1, 0x70, 0xa4, 0x07, 0x00, 0x00,
// 711 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x9c, 0x55, 0x5f, 0x4f, 0xdb, 0x30,
0x10, 0x27, 0x29, 0xb4, 0xe5, 0x5a, 0x28, 0xb3, 0x18, 0x8a, 0xd0, 0x36, 0xa1, 0x3c, 0xf1, 0x84,
0xd0, 0x26, 0xed, 0x8f, 0x2a, 0x98, 0xb2, 0xa2, 0x4d, 0x9d, 0x80, 0xa1, 0xb6, 0x68, 0xbc, 0x9a,
0xc4, 0xa4, 0x56, 0xdc, 0x38, 0x72, 0x5c, 0x26, 0xf6, 0x4d, 0xf6, 0x81, 0xf6, 0xa1, 0xf6, 0x36,
0xd9, 0xb1, 0xd3, 0xb4, 0x6a, 0xa7, 0xc1, 0x5b, 0x7e, 0x77, 0xf7, 0xbb, 0x3b, 0xdf, 0xbf, 0xc0,
0x56, 0x26, 0xf8, 0x1d, 0x65, 0xe4, 0x28, 0x13, 0x5c, 0x72, 0xd4, 0x30, 0xd0, 0x9f, 0x40, 0xeb,
0x9c, 0xe6, 0xf2, 0x82, 0xe4, 0x39, 0x8e, 0x09, 0xf2, 0xa1, 0xfd, 0x9d, 0x8b, 0x84, 0x71, 0x1c,
0x8d, 0x1e, 0x32, 0xe2, 0x39, 0x07, 0xce, 0xe1, 0xe6, 0x60, 0x4e, 0xa6, 0x6c, 0xae, 0x0a, 0xf6,
0x25, 0x9e, 0x90, 0xdc, 0x73, 0x0b, 0x9b, 0xaa, 0x0c, 0xed, 0x41, 0x3d, 0x08, 0x25, 0xbd, 0x27,
0x5e, 0x4d, 0x6b, 0x0d, 0xf2, 0xbb, 0xd0, 0x32, 0x76, 0xfd, 0xf4, 0x8e, 0x23, 0x04, 0xeb, 0xca,
0xde, 0x84, 0xd1, 0xdf, 0xc8, 0x83, 0x46, 0x8f, 0xa7, 0x92, 0xa4, 0x52, 0x7b, 0x6e, 0x0f, 0x2c,
0xf4, 0xbb, 0xd0, 0x09, 0x52, 0xcc, 0x1e, 0x72, 0x9a, 0xdb, 0x7c, 0x97, 0x39, 0xd8, 0x85, 0x8d,
0x0b, 0x1e, 0x11, 0x66, 0x12, 0x2b, 0x80, 0xff, 0x12, 0x6a, 0x41, 0x98, 0xa8, 0xc4, 0x86, 0x12,
0xcb, 0x69, 0x6e, 0x28, 0x06, 0xf9, 0x37, 0xd0, 0x0c, 0xc2, 0xa4, 0x37, 0x26, 0x61, 0xb2, 0xd4,
0xe9, 0x8c, 0xe7, 0x56, 0x79, 0xe8, 0x00, 0x5a, 0x67, 0x24, 0x0f, 0x05, 0xcd, 0x24, 0xe5, 0xa9,
0x79, 0x6d, 0x55, 0xe4, 0xdf, 0x00, 0x98, 0x27, 0x9f, 0xf3, 0x18, 0x6d, 0x83, 0xdb, 0x8f, 0xb4,
0xe7, 0xda, 0xc0, 0xed, 0x47, 0xe8, 0x05, 0x6c, 0xda, 0x82, 0x44, 0xc6, 0xf5, 0x4c, 0xa0, 0xb4,
0x23, 0x3a, 0x21, 0xb9, 0xc4, 0x93, 0xcc, 0xf8, 0x9e, 0x09, 0xfc, 0xdf, 0x0e, 0xb4, 0x7a, 0x9c,
0x31, 0x12, 0xca, 0xcf, 0x0c, 0xc7, 0x68, 0x1f, 0x9a, 0xfd, 0x54, 0x12, 0x71, 0x8f, 0x99, 0x89,
0x50, 0x62, 0xa5, 0x3b, 0x9b, 0x0a, 0xac, 0x93, 0x74, 0x0b, 0x9d, 0xc5, 0x4a, 0x67, 0x1b, 0x6c,
0x82, 0x94, 0x18, 0xbd, 0x02, 0xf8, 0x36, 0x95, 0xd9, 0x54, 0x5e, 0x61, 0x39, 0xf6, 0xd6, 0xb5,
0xb6, 0x22, 0x51, 0xc5, 0xfe, 0xc4, 0x78, 0x98, 0x78, 0x1b, 0x45, 0xb1, 0x35, 0x50, 0x3d, 0xbc,
0x24, 0xf2, 0x07, 0x17, 0x89, 0x57, 0xd7, 0x72, 0x0b, 0x55, 0x6d, 0xf5, 0x60, 0x35, 0x8a, 0xda,
0xaa, 0x6f, 0xff, 0x2b, 0xb4, 0x47, 0x02, 0xd3, 0xd4, 0x36, 0x55, 0xe5, 0x8a, 0x25, 0xd6, 0x11,
0x8b, 0x1e, 0x94, 0x78, 0x21, 0x1f, 0x77, 0x31, 0x1f, 0xff, 0x97, 0x03, 0x5b, 0x67, 0xe4, 0x8e,
0xa6, 0xc4, 0x7a, 0x3b, 0x80, 0xd6, 0x90, 0x88, 0x7b, 0x1a, 0x92, 0xca, 0x44, 0x57, 0x45, 0xe8,
0x10, 0x3a, 0x41, 0x96, 0x31, 0x1a, 0xea, 0x72, 0xe8, 0xd6, 0x17, 0x8e, 0x17, 0xc5, 0x6a, 0xf4,
0x87, 0x21, 0x49, 0xb1, 0xa0, 0x5c, 0x9b, 0x15, 0xd5, 0x9a, 0x93, 0x55, 0xe7, 0x77, 0x7d, 0x7e,
0x7e, 0x87, 0xd0, 0x19, 0x86, 0x63, 0x12, 0x4d, 0x59, 0x99, 0xdc, 0x0e, 0xd4, 0x82, 0x2c, 0x33,
0x49, 0xa9, 0xcf, 0xb2, 0x40, 0xee, 0xac, 0x40, 0xaa, 0x20, 0x43, 0x29, 0xb0, 0x24, 0xf1, 0x83,
0x6d, 0x90, 0xc5, 0xaf, 0xff, 0x34, 0xca, 0xf9, 0xba, 0x88, 0x05, 0x7a, 0x0b, 0x0d, 0x83, 0xd0,
0xee, 0x91, 0xdd, 0xf9, 0xca, 0xca, 0xed, 0x3f, 0x2b, 0xa5, 0x76, 0xde, 0xfd, 0xb5, 0x63, 0x07,
0x7d, 0x84, 0x1d, 0x0d, 0xfa, 0x29, 0x95, 0x4f, 0x72, 0xd0, 0x85, 0xa6, 0x5d, 0x4e, 0xe4, 0xcd,
0x4c, 0xe6, 0xf7, 0x75, 0x15, 0xf9, 0x1d, 0xd4, 0x47, 0xd3, 0x94, 0xa6, 0xf1, 0x23, 0x62, 0x1e,
0x3a, 0xc7, 0x0e, 0x3a, 0x85, 0xb6, 0x3a, 0x5f, 0xe5, 0xb8, 0x2e, 0xa7, 0xcf, 0xa4, 0x95, 0x5b,
0xa7, 0x03, 0x9f, 0xc0, 0xf6, 0x75, 0x16, 0x0b, 0x1c, 0x91, 0x27, 0x3d, 0xfa, 0x04, 0x5a, 0x4a,
0xfd, 0x6f, 0xee, 0x52, 0xa9, 0xa6, 0x07, 0x80, 0xb4, 0xaf, 0xe2, 0x38, 0x3e, 0x29, 0x83, 0x53,
0xe8, 0x18, 0xab, 0x01, 0x67, 0xec, 0x16, 0x87, 0xc9, 0xa3, 0xf9, 0xbd, 0x31, 0x56, 0xb3, 0x24,
0xe8, 0xcf, 0xe2, 0x1c, 0x3c, 0x8a, 0xff, 0x01, 0xc0, 0x9c, 0xa0, 0x79, 0x6a, 0xe5, 0x2e, 0xad,
0xa2, 0xbe, 0x87, 0xa6, 0x5e, 0x7b, 0xd5, 0xf6, 0xe7, 0xa5, 0x49, 0xf5, 0x12, 0xac, 0x62, 0x1e,
0x43, 0xbd, 0xd8, 0x71, 0xb4, 0x57, 0x1a, 0xcc, 0x2d, 0xfd, 0x7e, 0xbb, 0x4a, 0xf4, 0xd7, 0xd0,
0x91, 0x62, 0x30, 0x22, 0x57, 0x55, 0x77, 0x89, 0xfd, 0x75, 0x16, 0xe1, 0xff, 0xb6, 0xef, 0x42,
0xd3, 0xae, 0x76, 0x65, 0xfa, 0x17, 0xb6, 0x7d, 0xf5, 0xf4, 0x37, 0xbf, 0x90, 0x94, 0x88, 0xd5,
0xe1, 0x96, 0x13, 0x6f, 0xeb, 0xfa, 0x67, 0xfe, 0xe6, 0x6f, 0x00, 0x00, 0x00, 0xff, 0xff, 0xe0,
0x92, 0xa6, 0x6c, 0xdd, 0x07, 0x00, 0x00,
}
// Reference imports to suppress errors if they are not otherwise used.
......@@ -665,6 +664,7 @@ type ProfileMgrClient interface {
Delete(ctx context.Context, in *ProfileInfo, opts ...grpc.CallOption) (*Ack, error)
Update(ctx context.Context, in *ProfileInfo, opts ...grpc.CallOption) (*Ack, error)
Schedule(ctx context.Context, in *ScheduleMessage, opts ...grpc.CallOption) (ProfileMgr_ScheduleClient, error)
Generate(ctx context.Context, in *ProfileInfo, opts ...grpc.CallOption) (ProfileMgr_GenerateClient, error)
}
type profileMgrClient struct {
......@@ -1117,6 +1117,38 @@ func (x *profileMgrScheduleClient) Recv() (*AckCheck, error) {
return m, nil
}
func (c *profileMgrClient) Generate(ctx context.Context, in *ProfileInfo, opts ...grpc.CallOption) (ProfileMgr_GenerateClient, error) {
stream, err := c.cc.NewStream(ctx, &_ProfileMgr_serviceDesc.Streams[13], "/profile.ProfileMgr/Generate", opts...)
if err != nil {
return nil, err
}
x := &profileMgrGenerateClient{stream}
if err := x.ClientStream.SendMsg(in); err != nil {
return nil, err
}
if err := x.ClientStream.CloseSend(); err != nil {
return nil, err
}
return x, nil
}
type ProfileMgr_GenerateClient interface {
Recv() (*AckCheck, error)
grpc.ClientStream
}
type profileMgrGenerateClient struct {
grpc.ClientStream
}
func (x *profileMgrGenerateClient) Recv() (*AckCheck, error) {
m := new(AckCheck)
if err := x.ClientStream.RecvMsg(m); err != nil {
return nil, err
}
return m, nil
}
// ProfileMgrServer is the server API for ProfileMgr service.
type ProfileMgrServer interface {
Profile(*ProfileInfo, ProfileMgr_ProfileServer) error
......@@ -1135,59 +1167,7 @@ type ProfileMgrServer interface {
Delete(context.Context, *ProfileInfo) (*Ack, error)
Update(context.Context, *ProfileInfo) (*Ack, error)
Schedule(*ScheduleMessage, ProfileMgr_ScheduleServer) error
}
// UnimplementedProfileMgrServer can be embedded to have forward compatible implementations.
type UnimplementedProfileMgrServer struct {
}
func (*UnimplementedProfileMgrServer) Profile(req *ProfileInfo, srv ProfileMgr_ProfileServer) error {
return status.Errorf(codes.Unimplemented, "method Profile not implemented")
}
func (*UnimplementedProfileMgrServer) CheckInitProfile(req *ProfileInfo, srv ProfileMgr_CheckInitProfileServer) error {
return status.Errorf(codes.Unimplemented, "method CheckInitProfile not implemented")
}
func (*UnimplementedProfileMgrServer) Analysis(req *AnalysisMessage, srv ProfileMgr_AnalysisServer) error {
return status.Errorf(codes.Unimplemented, "method Analysis not implemented")
}
func (*UnimplementedProfileMgrServer) Tuning(srv ProfileMgr_TuningServer) error {
return status.Errorf(codes.Unimplemented, "method Tuning not implemented")
}
func (*UnimplementedProfileMgrServer) ListWorkload(req *ProfileInfo, srv ProfileMgr_ListWorkloadServer) error {
return status.Errorf(codes.Unimplemented, "method ListWorkload not implemented")
}
func (*UnimplementedProfileMgrServer) UpgradeProfile(req *ProfileInfo, srv ProfileMgr_UpgradeProfileServer) error {
return status.Errorf(codes.Unimplemented, "method UpgradeProfile not implemented")
}
func (*UnimplementedProfileMgrServer) InfoProfile(req *ProfileInfo, srv ProfileMgr_InfoProfileServer) error {
return status.Errorf(codes.Unimplemented, "method InfoProfile not implemented")
}
func (*UnimplementedProfileMgrServer) CheckActiveProfile(req *ProfileInfo, srv ProfileMgr_CheckActiveProfileServer) error {
return status.Errorf(codes.Unimplemented, "method CheckActiveProfile not implemented")
}
func (*UnimplementedProfileMgrServer) ProfileRollback(req *ProfileInfo, srv ProfileMgr_ProfileRollbackServer) error {
return status.Errorf(codes.Unimplemented, "method ProfileRollback not implemented")
}
func (*UnimplementedProfileMgrServer) Charaterization(req *ProfileInfo, srv ProfileMgr_CharaterizationServer) error {
return status.Errorf(codes.Unimplemented, "method Charaterization not implemented")
}
func (*UnimplementedProfileMgrServer) Collection(req *CollectFlag, srv ProfileMgr_CollectionServer) error {
return status.Errorf(codes.Unimplemented, "method Collection not implemented")
}
func (*UnimplementedProfileMgrServer) Training(req *TrainMessage, srv ProfileMgr_TrainingServer) error {
return status.Errorf(codes.Unimplemented, "method Training not implemented")
}
func (*UnimplementedProfileMgrServer) Define(ctx context.Context, req *DefineMessage) (*Ack, error) {
return nil, status.Errorf(codes.Unimplemented, "method Define not implemented")
}
func (*UnimplementedProfileMgrServer) Delete(ctx context.Context, req *ProfileInfo) (*Ack, error) {
return nil, status.Errorf(codes.Unimplemented, "method Delete not implemented")
}
func (*UnimplementedProfileMgrServer) Update(ctx context.Context, req *ProfileInfo) (*Ack, error) {
return nil, status.Errorf(codes.Unimplemented, "method Update not implemented")
}
func (*UnimplementedProfileMgrServer) Schedule(req *ScheduleMessage, srv ProfileMgr_ScheduleServer) error {
return status.Errorf(codes.Unimplemented, "method Schedule not implemented")
Generate(*ProfileInfo, ProfileMgr_GenerateServer) error
}
func RegisterProfileMgrServer(s *grpc.Server, srv ProfileMgrServer) {
......@@ -1526,6 +1506,27 @@ func (x *profileMgrScheduleServer) Send(m *AckCheck) error {
return x.ServerStream.SendMsg(m)
}
func _ProfileMgr_Generate_Handler(srv interface{}, stream grpc.ServerStream) error {
m := new(ProfileInfo)
if err := stream.RecvMsg(m); err != nil {
return err
}
return srv.(ProfileMgrServer).Generate(m, &profileMgrGenerateServer{stream})
}
type ProfileMgr_GenerateServer interface {
Send(*AckCheck) error
grpc.ServerStream
}
type profileMgrGenerateServer struct {
grpc.ServerStream
}
func (x *profileMgrGenerateServer) Send(m *AckCheck) error {
return x.ServerStream.SendMsg(m)
}
var _ProfileMgr_serviceDesc = grpc.ServiceDesc{
ServiceName: "profile.ProfileMgr",
HandlerType: (*ProfileMgrServer)(nil),
......@@ -1610,6 +1611,11 @@ var _ProfileMgr_serviceDesc = grpc.ServiceDesc{
Handler: _ProfileMgr_Schedule_Handler,
ServerStreams: true,
},
{
StreamName: "Generate",
Handler: _ProfileMgr_Generate_Handler,
ServerStreams: true,
},
},
Metadata: "profile.proto",
}
......@@ -33,6 +33,7 @@ service ProfileMgr {
rpc Delete(ProfileInfo) returns (Ack) {}
rpc Update(ProfileInfo) returns (Ack) {}
rpc Schedule(ScheduleMessage) returns (stream AckCheck) {}
rpc Generate(ProfileInfo) returns (stream AckCheck) {}
}
message ListMessage {
......
......@@ -44,6 +44,7 @@ const (
DefaultProfilePath = DefaultPath + "profiles"
DefaultConfPath = "/etc/atuned/"
DefaultTuningPath = DefaultConfPath + "tuning/"
DefaultRulePath = DefaultConfPath + "rules/"
DefaultScriptPath = "/usr/libexec/atuned/scripts"
DefaultCollectorPath = "/usr/libexec/atuned/collector"
DefaultAnalysisPath = "/usr/libexec/atuned/analysis"
......@@ -90,6 +91,7 @@ const (
//tuning config
const (
TuningFile string = DefaultTempPath + "/tuning.log"
TuningRuleFile string = "tuning_rules.grl"
TuningRestoreConfig string = "-tuning-restore.conf"
DefaultTimeFormat string = "2006-01-02 15:04:05"
)
......
......@@ -14,11 +14,11 @@
package tuning
import (
"encoding/json"
"fmt"
"gitee.com/openeuler/A-Tune/common/config"
"gitee.com/openeuler/A-Tune/common/http"
"gitee.com/openeuler/A-Tune/common/log"
"encoding/json"
"fmt"
"io/ioutil"
"strings"
......
/*
* Copyright (c) 2019 Huawei Technologies Co., Ltd.
* A-Tune is licensed under the Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
* PURPOSE.
* See the Mulan PSL v2 for more details.
* Create: 2020-07-23
*/
package tuning
import (
"fmt"
PB "gitee.com/openeuler/A-Tune/api/profile"
"gitee.com/openeuler/A-Tune/common/config"
"gitee.com/openeuler/A-Tune/common/log"
"gitee.com/openeuler/A-Tune/common/project"
"gitee.com/openeuler/A-Tune/common/utils"
"gopkg.in/yaml.v2"
"os"
"path/filepath"
"github.com/newm4n/grool/builder"
gContext "github.com/newm4n/grool/context"
"github.com/newm4n/grool/engine"
"github.com/newm4n/grool/model"
"github.com/newm4n/grool/pkg"
)
// TuningData : the struct which store the collection data
type TuningData struct {
CacheMissRatio float64 `mapstructure:"PERF.STAT.CACHE-MISS-RATIO"`
DtlbLoadMissRatio float64 `mapstructure:"PERF.STAT.DTLB-LOAD-MISS-RATIO"`
Ipc float64 `mapstructure:"PERF.STAT.IPC"`
ItlbLoadMissRatio float64 `mapstructure:"PERF.STAT.ITLB-LOAD-MISS-RATIO"`
Migrations float64 `mapstructure:"PERF.STAT.migrations"`
MemoryBound float64 `mapstructure:"MEMORY-BOUND"`
Mpki float64 `mapstructure:"PERF.STAT.MPKI"`
Sbpc float64 `mapstructure:"PERF.STAT.SBPC"`
Sbpi float64 `mapstructure:"PERF.STAT.SBPI"`
StorageUtil float64 `mapstructure:"STORAGE.STAT.util"`
TotalUtil float64 `mapstructure:"MEM.BANDWIDTH.Total_Util"`
AquSz float64 `mapstructure:"STORAGE.STAT.aqu-sz"`
Cswchs float64 `mapstructure:"SYS.TASKS.cswchs"`
Cutil float64 `mapstructure:"CPU.STAT.cutil"`
Errs float64 `mapstructure:"NET.STAT.errs"`
Ifutil float64 `mapstructure:"NET.STAT.ifutil"`
IoBi float64 `mapstructure:"MEM.VMSTAT.io.bi"`
IoBo float64 `mapstructure:"MEM.VMSTAT.io.bo"`
Iowait float64 `mapstructure:"CPU.STAT.iowait"`
Irq float64 `mapstructure:"CPU.STAT.irq"`
Ldavg1 float64 `mapstructure:"SYS.LDAVG.ldavg-1"`
Ldavg5 float64 `mapstructure:"SYS.LDAVG.ldavg-5"`
MemorySwpt float64 `mapstructure:"MEM.VMSTAT.memory.swpt"`
Nice float64 `mapstructure:"CPU.STAT.nice"`
PlistSz float64 `mapstructure:"SYS.LDAVG.plist-sz"`
Procs float64 `mapstructure:"SYS.TASKS.procs"`
ProcsB float64 `mapstructure:"MEM.VMSTAT.procs.b"`
ProcsR float64 `mapstructure:"MEM.STAT.procs.r"`
RMbs float64 `mapstructure:"STORAGE.STAT.rMBs"`
WMbs float64 `mapstructure:"STORAGE.STAT.wMBs"`
RAwait float64 `mapstructure:"STORAGE.STAT.r_await"`
WAwait float64 `mapstructure:"STORAGE.STAT.w_await"`
RareqSz float64 `mapstructure:"STORAGE.STAT.rareq-sz"`
WareqSz float64 `mapstructure:"STORAGE.STAT.wareq-sz"`
Rrqm float64 `mapstructure:"STORAGE.STAT.rrqm"`
Wrqm float64 `mapstructure:"STORAGE.STAT.wrqm"`
Rs float64 `mapstructure:"STORAGE.STAT.rs"`
Ws float64 `mapstructure:"STORAGE.STAT.ws"`
RunqSz float64 `mapstructure:"SYS.LDAVG.runq-sz"`
RxKbs float64 `mapstructure:"NET.STAT.rxkBs"`
RxPcks float64 `mapstructure:"NET.STAT.rxpcks"`
TxKbs float64 `mapstructure:"NET.STAT.txkBs"`
TxPcks float64 `mapstructure:"NET.STAT.txpcks"`
Soft float64 `mapstructure:"CPU.STAT.soft"`
Steal float64 `mapstructure:"CPU.STAT.steal"`
Sys float64 `mapstructure:"CPU.STAT.sys"`
SystemCs float64 `mapstructure:"MEM.VMSTAT.system.cs"`
SystemIn float64 `mapstructure:"MEM.VMSTAT.system.in"`
User float64 `mapstructure:"CPU.STAT.usr"`
Util float64 `mapstructure:"CPU.STAT.util"`
UtilCpu float64 `mapstructure:"MEM.VMSTAT.util.cpu"`
UtilSwap float64 `mapstructure:"MEM.VMSTAT.util.swap"`
}
// TuningFile used to store the object which match the tuning rule
type TuningFile struct {
prjs *[]project.YamlPrjSvr `yaml:"-"`
PrjSrv *project.YamlPrjSvr
ch chan *PB.AckCheck
}
// NewTuningFile method create a TuningFile instance
func NewTuningFile(workloadType string, ch chan *PB.AckCheck) *TuningFile {
tuningFile := new(TuningFile)
tuningFile.PrjSrv = new(project.YamlPrjSvr)
tuningFile.PrjSrv.Project = workloadType
tuningFile.PrjSrv.Maxiterations = 20
prjs := make([]project.YamlPrjSvr, 0)
tuningFile.prjs = &prjs
tuningFile.ch = ch
return tuningFile
}
// Load method load the yaml come with the atuned
func (t TuningFile) Load() error {
err := filepath.Walk(config.DefaultTuningPath, func(path string, info os.FileInfo, err error) error {
if !info.IsDir() {
prj := new(project.YamlPrjSvr)
if err := utils.ParseFile(path, "yaml", &prj); err != nil {
return fmt.Errorf("load %s faild, err: %v", path, err)
}
log.Infof("project:%s load %s success", prj.Project, path)
*t.prjs = append(*t.prjs, *prj)
}
return nil
})
if err != nil {
return err
}
return nil
}
// AppendObject add the tuning object which match the rules
func (t *TuningFile) AppendObject(object string) {
log.Infof("append %s object to dest tuning file", object)
var exist bool = false
for _, prj := range *t.prjs {
for _, obj := range prj.Object {
if obj.Name != object {
continue
}
exist = true
t.PrjSrv.Object = append(t.PrjSrv.Object, obj)
break
}
if exist {
log.Infof("find object: %s", object)
t.ch <- &PB.AckCheck{Name: fmt.Sprintf(" appending parameter: %s", object)}
return
}
}
t.ch <- &PB.AckCheck{Name: fmt.Sprintf(" appending parameter: %s, but not founded", object)}
}
// Save method save the project to file
func (t *TuningFile) Save(dstFile string) error {
data, err := yaml.Marshal(t.PrjSrv)
if err != nil {
return err
}
log.Debugf("data content: %s", string(data))
err = utils.WriteFile(dstFile, string(data), utils.FilePerm,
os.O_WRONLY|os.O_CREATE|os.O_TRUNC)
if err != nil {
log.Error(err)
return err
}
return nil
}
type RuleEngine struct {
DataContext *gContext.DataContext
Grool *engine.Grool
KnowledgeBase *model.KnowledgeBase
}
func NewRuleEngine(srcFile string) *RuleEngine {
ruleEngine := new(RuleEngine)
ruleEngine.KnowledgeBase = model.NewKnowledgeBase()
ruleBuilder := builder.NewRuleBuilder(ruleEngine.KnowledgeBase)
fileRes := pkg.NewFileResource(srcFile)
err := ruleBuilder.BuildRuleFromResource(fileRes)
if err != nil {
return nil
}
ruleEngine.DataContext = gContext.NewDataContext()
ruleEngine.Grool = engine.NewGroolEngine()
return ruleEngine
}
func (r *RuleEngine) AddContext(key string, obj interface{}) error {
err := r.DataContext.Add(key, obj)
if err != nil {
return err
}
return nil
}
func (r *RuleEngine) Execute() error {
if r.Grool == nil {
return fmt.Errorf("grool engine is nill")
}
return r.Grool.Execute(r.DataContext, r.KnowledgeBase)
}
......@@ -12,10 +12,11 @@ require (
github.com/golang/protobuf v1.3.1
github.com/mattn/go-sqlite3 v1.11.0
github.com/mitchellh/mapstructure v1.1.2
github.com/newm4n/grool v1.0.2
github.com/sirupsen/logrus v1.4.2
github.com/smartystreets/goconvey v0.0.0-20190731233626-505e41936337 // indirect
github.com/urfave/cli v1.20.0
golang.org/x/net v0.0.0-20190628185345-da137c7871d7
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80
google.golang.org/grpc v1.22.0
gopkg.in/ini.v1 v1.48.0 // indirect
gopkg.in/yaml.v2 v2.2.2
......
......@@ -7,6 +7,7 @@ github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWX
github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/antlr/antlr4 v0.0.0-20190623224521-a770ff26ccc4/go.mod h1:T7PbCXFs94rrTttyxjbyT5+/1V8T2TYDejxUfHJjw1Y=
github.com/antlr/antlr4 v0.0.0-20190726171924-e4737db19f4f h1:GhBxi/Go5GISuLutOqoZ3RaWUpwiruwzlDPXLF0G40g=
github.com/antlr/antlr4 v0.0.0-20190726171924-e4737db19f4f/go.mod h1:T7PbCXFs94rrTttyxjbyT5+/1V8T2TYDejxUfHJjw1Y=
github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
......@@ -42,6 +43,8 @@ github.com/go-xorm/xorm v0.7.4 h1:g/NgC590SzqV5VKmdRDNe/K3Holw3YJUCXX28r+rFGw=
github.com/go-xorm/xorm v0.7.4/go.mod h1:vpza5fydeRgt+stvo9qgMhSNohYqmNt0I1/D6hkCekA=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/golang-collections/collections v0.0.0-20130729185459-604e922904d3 h1:zN2lZNZRflqFyxVaTIU61KNKQ9C0055u9CAfpmqUvo4=
github.com/golang-collections/collections v0.0.0-20130729185459-604e922904d3/go.mod h1:nPpo7qLxd6XL3hWJG/O60sR8ZKfMCiIoNap5GvD12KU=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
......@@ -69,6 +72,8 @@ github.com/jackc/pgx v3.3.0+incompatible/go.mod h1:0ZGrqGqkRlliWnWB4zKnWtjbSWbGk
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
github.com/juju/errors v0.0.0-20190806202954-0232dcc7464d h1:hJXjZMxj0SWlMoQkzeZDLi2cmeiWKa7y1B8Rg+qaoEc=
github.com/juju/errors v0.0.0-20190806202954-0232dcc7464d/go.mod h1:W54LbzXuIE0boCoNJfwqpmkKJ1O4TCTZMetAt6jGk7Q=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk=
......@@ -88,6 +93,8 @@ github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5
github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/newm4n/grool v1.0.2 h1:jdL8LAnWoGoNyeyHrzumljUM6RaFhVsSp0whEqUNLqU=
github.com/newm4n/grool v1.0.2/go.mod h1:h0KB8fnrHYDz2uB2nNbVB9PvhZGf/sWMUHZM8ADoAMM=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
......@@ -132,11 +139,13 @@ golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnf
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c h1:Vj5n4GlwjmQteupaxJ9+0FNOmBrHfq7vN4btdGoDZgI=
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
......@@ -145,8 +154,12 @@ golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73r
golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190628185345-da137c7871d7 h1:rTIdg5QFRR7XCaK4LCjBiPbx8j4DQRpdYMnGn/bJUEU=
golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80 h1:Ao/3l156eZf2AW5wK8a7/smtodRU+gha3+BeqJ69lRk=
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
......@@ -160,20 +173,28 @@ golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5h
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894 h1:Cz4ceDQGXuKRnVBDTS23GTn/pU5OE2C0WrNTOYK1Uuc=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a h1:aYOabOQFp6Vj6W1F80affTUvO9UxmJRx8K0gsfABByQ=
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2 h1:z99zHgr7hKfrUcX/KsoJk5FJfjTceCKIp96+biqP4To=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190813034749-528a2984e271/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0 h1:/wp5JvzpHIxhs/dumFmF7BXTf3Z+dd4uXta4kVyO508=
......
......@@ -10,6 +10,6 @@
# Create: 2019-10-29
# atune-adm completion -*- shell-script -*-
complete -W "upgrade profile analysis check info list rollback tuning collection define undefine update train help" atune-adm
complete -W "upgrade profile analysis check info list rollback tuning collection define undefine update train generate help" atune-adm
# ex: filetype=sh
/*
* Copyright (c) 2019 Huawei Technologies Co., Ltd.
* A-Tune is licensed under the Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
* PURPOSE.
* See the Mulan PSL v2 for more details.
* Create: 2020-07-23
*/
package profile
import (
"fmt"
PB "gitee.com/openeuler/A-Tune/api/profile"
"gitee.com/openeuler/A-Tune/common/client"
SVC "gitee.com/openeuler/A-Tune/common/service"
"gitee.com/openeuler/A-Tune/common/utils"
"io"
"github.com/urfave/cli"
CTX "golang.org/x/net/context"
)
var profileGenerateCommand = cli.Command{
Name: "generate",
Usage: "generate the tuning yaml profile based on the rules",
UsageText: "atune-adm generate OPTIONS",
Flags: []cli.Flag{
cli.StringFlag{
Name: "project,p",
Usage: "the filename and project name to be generated",
Value: "default",
},
},
Description: func() string {
desc := "generate the tuning yaml profile depend on the rules"
return desc
}(),
Action: profileGenerate,
}
func init() {
svc := SVC.ProfileService{
Name: "opt.profile.generate",
Desc: "opt profile generate",
NewInst: newProfileGenerate,
}
if err := SVC.AddService(&svc); err != nil {
fmt.Printf("Failed to load profile generate service : %s\n", err)
return
}
}
func newProfileGenerate(ctx *cli.Context, opts ...interface{}) (interface{}, error) {
return profileGenerateCommand, nil
}
func profileGenerate(ctx *cli.Context) error {
if err := utils.CheckArgs(ctx, 0, utils.ConstExactArgs); err != nil {
return err
}
c, err := client.NewClientFromContext(ctx)
if err != nil {
return err
}
defer c.Close()
svc := PB.NewProfileMgrClient(c.Connection())
stream, err := svc.Generate(CTX.Background(), &PB.ProfileInfo{Name: ctx.String("project")})
if err != nil {
fmt.Println(err)
return nil
}
for {
reply, err := stream.Recv()
if err == io.EOF {
break
}
if err != nil {
return err
}
utils.Print(reply)
}
return nil
}
......@@ -46,6 +46,7 @@ import (
"time"
"github.com/go-ini/ini"
"github.com/mitchellh/mapstructure"
"github.com/urfave/cli"
"google.golang.org/grpc"
)
......@@ -68,7 +69,8 @@ type CollectorPost struct {
// RespCollectorPost : the response of collection servie
type RespCollectorPost struct {
Path string `json:"path"`
Path string `json:"path"`
Data map[string]interface{} `json:"data"`
}
// ClassifyPostBody : the body send to classify service
......@@ -573,6 +575,7 @@ func (s *ProfileServer) Tuning(stream PB.ProfileMgr_TuningServer) error {
}()
var optimizer = tuning.Optimizer{}
for {
reply, err := stream.Recv()
if err == io.EOF {
......@@ -606,7 +609,6 @@ func (s *ProfileServer) Tuning(stream PB.ProfileMgr_TuningServer) error {
if err = tuning.CheckServerPrj(data, &optimizer); err != nil {
return err
}
//content == nil means in restore config
if content == nil {
if err = optimizer.RestoreConfigTuned(ch); err != nil {
......@@ -1237,3 +1239,155 @@ func (s *ProfileServer) Schedule(message *PB.ScheduleMessage,
_ = stream.Send(&PB.AckCheck{Name: "schedule finished"})
return nil
}
func (s *ProfileServer) collection() (*RespCollectorPost, error) {
//1. get the dimension structure of the system data to be collected
collections, err := sqlstore.GetCollections()
if err != nil {
log.Errorf("inquery collection tables error: %v", err)
return nil, err
}
// 1.1 send the collect data command to the monitor service
monitors := make([]Monitor, 0)
for _, collection := range collections {
re := regexp.MustCompile(`\{([^}]+)\}`)
matches := re.FindAllStringSubmatch(collection.Metrics, -1)
if len(matches) > 0 {
for _, match := range matches {
if len(match) < 2 {
continue
}
var value string
if s.Raw.Section("system").Haskey(match[1]) {
value = s.Raw.Section("system").Key(match[1]).Value()
} else if s.Raw.Section("server").Haskey(match[1]) {
value = s.Raw.Section("server").Key(match[1]).Value()
} else {
return nil, fmt.Errorf("%s is not exist in the system or server section", match[1])
}
re = regexp.MustCompile(`\{(` + match[1] + `)\}`)
collection.Metrics = re.ReplaceAllString(collection.Metrics, value)
}
}
monitor := Monitor{Module: collection.Module, Purpose: collection.Purpose, Field: collection.Metrics}
monitors = append(monitors, monitor)
}
sampleNum := s.Raw.Section("server").Key("sample_num").MustInt(20)
collectorBody := new(CollectorPost)
collectorBody.SampleNum = sampleNum
collectorBody.Monitors = monitors
collectorBody.File = "/run/atuned/test.csv"
log.Infof("tuning collector body is:", collectorBody)
respCollectPost, err := collectorBody.Post()
if err != nil {
return nil, err
}
return respCollectPost, nil
}
func (s *ProfileServer) classify(dataPath string) (string, string, error) {
//2. send the collected data to the model for completion type identification
var resourceLimit string
var workloadType string
dataPath, err := Post("classification", "file", dataPath)
if err != nil {
log.Errorf("Failed transfer file to server: %v", err)
return workloadType, resourceLimit, err
}
body := new(ClassifyPostBody)
body.Data = dataPath
body.ModelPath = path.Join(config.DefaultAnalysisPath, "models")
respPostIns, err := body.Post()
if err != nil {
return workloadType, resourceLimit, err
}
log.Infof("workload %s, cluster result resource limit: %s",
respPostIns.WorkloadType, respPostIns.ResourceLimit)
resourceLimit = respPostIns.ResourceLimit
workloadType = respPostIns.WorkloadType
return workloadType, resourceLimit, nil
}
func (s *ProfileServer) Getworkload() (string, error) {
respCollectPost, err := s.collection()
if err != nil {
return "", err
}
workload, _, err := s.classify(respCollectPost.Path)
if err != nil {
return "", err
}
if len(workload) == 0 {
return "", fmt.Errorf("workload is empty")
}
return workload, nil
}
// Generate method generate the yaml file for tuning
func (s *ProfileServer) Generate(message *PB.ProfileInfo, stream PB.ProfileMgr_GenerateServer) error {
ch := make(chan *PB.AckCheck)
defer close(ch)
go func() {
for value := range ch {
_ = stream.Send(value)
}
}()
_ = stream.Send(&PB.AckCheck{Name: fmt.Sprintf("1.Start to analysis the system bottleneck")})
respCollectPost, err := s.collection()
if err != nil {
return err
}
log.Infof("collect data response body is: %+v", respCollectPost)
collectData := respCollectPost.Data
projectName := message.GetName()
_ = stream.Send(&PB.AckCheck{Name: fmt.Sprintf("2.Finding potential tuning parameters")})
var tuningData tuning.TuningData
err = mapstructure.Decode(collectData, &tuningData)
if err != nil {
return err
}
log.Infof("decode to structure is: %+v", tuningData)
ruleFile := path.Join(config.DefaultRulePath, config.TuningRuleFile)
engine := tuning.NewRuleEngine(ruleFile)
if engine == nil {
fmt.Errorf("create rules engine failed")
}
tuningFile := tuning.NewTuningFile(projectName, ch)
err = tuningFile.Load()
if err != nil {
return err
}
engine.AddContext("TuningData", &tuningData)
engine.AddContext("TuningFile", tuningFile)
err = engine.Execute()
if err != nil {
return err
}
if len(tuningFile.PrjSrv.Object) <= 0 {
_ = stream.Send(&PB.AckCheck{Name: fmt.Sprintf(" No tuning parameters founed")})
return nil
}
dstFile := path.Join(config.DefaultTuningPath, fmt.Sprintf("%s.yaml", projectName))
log.Infof("generate tuning file: %s", dstFile)
err = tuningFile.Save(dstFile)
if err != nil {
return err
}
_ = stream.Send(&PB.AckCheck{Name: fmt.Sprintf("3. Generate tuning project: %s\n project name: %s", dstFile, projectName)})
return nil
}
rule MemUtil "When the Memory Total_Util is greater than 15 append the prefetcher object." salience 10 {
when
TuningData.TotalUtil > 10
then
TuningFile.AppendObject("prefetcher");
}
rule CpuBind "When sys is greater than usr append the cpu.band object." {
when
TuningData.Sys / TuningData.User > 1
then
TuningFile.AppendObject("cpu.bind");
}
rule CutilCpu "When cutil is greater than util.cpu append the kernel.numa_balancing object." {
when
TuningData.Cutil / TuningData.UtilCpu > 1.05
then
TuningFile.AppendObject("kernel.numa_balancing");
}
rule Migrations "When perf stat migrations item is greater than 40000 append the kernel.sched_migration_cost_ns." {
when
TuningData.Migrations > 40000
then
TuningFile.AppendObject("kernel.sched_migration_cost_ns");
}
Copyright (c) 2012 Caleb Doxsey
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
\ No newline at end of file
package stack
type (
Stack struct {
top *node
length int
}
node struct {
value interface{}
prev *node
}
)
// Create a new stack
func New() *Stack {
return &Stack{nil,0}
}
// Return the number of items in the stack
func (this *Stack) Len() int {
return this.length
}
// View the top item on the stack
func (this *Stack) Peek() interface{} {
if this.length == 0 {
return nil
}
return this.top.value
}
// Pop the top item of the stack and return it
func (this *Stack) Pop() interface{} {
if this.length == 0 {
return nil
}
n := this.top
this.top = n.prev
this.length--
return n.value
}
// Push a value onto the top of the stack
func (this *Stack) Push(value interface{}) {
n := &node{value,this.top}
this.top = n
this.length++
}
\ No newline at end of file
# Compiled Object files, Static and Dynamic libs (Shared Objects)
*.o
*.a
*.so
# Folders
_obj
_test
# Architecture specific extensions/prefixes
*.[568vq]
[568vq].out
*.cgo1.go
*.cgo2.c
_cgo_defun.c
_cgo_gotypes.go
_cgo_export.*
_testmain.go
*.exe
*.test
All files in this repository are licensed as follows. If you contribute
to this repository, it is assumed that you license your contribution
under the same license unless you state otherwise.
All files Copyright (C) 2015 Canonical Ltd. unless otherwise specified in the file.
This software is licensed under the LGPLv3, included below.
As a special exception to the GNU Lesser General Public License version 3
("LGPL3"), the copyright holders of this Library give you permission to
convey to a third party a Combined Work that links statically or dynamically
to this Library without providing any Minimal Corresponding Source or
Minimal Application Code as set out in 4d or providing the installation
information set out in section 4e, provided that you comply with the other
provisions of LGPL3 and provided that you meet, for the Application the
terms and conditions of the license(s) which apply to the Application.
Except as stated in this special exception, the provisions of LGPL3 will
continue to comply in full to this Library. If you modify this Library, you
may apply this exception to your version of this Library, but you are not
obliged to do so. If you do not wish to do so, delete this exception
statement from your version. This exception does not (and cannot) modify any
license terms which apply to the Application, with which you must still
comply.
GNU LESSER GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
This version of the GNU Lesser General Public License incorporates
the terms and conditions of version 3 of the GNU General Public
License, supplemented by the additional permissions listed below.
0. Additional Definitions.
As used herein, "this License" refers to version 3 of the GNU Lesser
General Public License, and the "GNU GPL" refers to version 3 of the GNU
General Public License.
"The Library" refers to a covered work governed by this License,
other than an Application or a Combined Work as defined below.
An "Application" is any work that makes use of an interface provided
by the Library, but which is not otherwise based on the Library.
Defining a subclass of a class defined by the Library is deemed a mode
of using an interface provided by the Library.
A "Combined Work" is a work produced by combining or linking an
Application with the Library. The particular version of the Library
with which the Combined Work was made is also called the "Linked
Version".
The "Minimal Corresponding Source" for a Combined Work means the
Corresponding Source for the Combined Work, excluding any source code
for portions of the Combined Work that, considered in isolation, are
based on the Application, and not on the Linked Version.
The "Corresponding Application Code" for a Combined Work means the
object code and/or source code for the Application, including any data
and utility programs needed for reproducing the Combined Work from the
Application, but excluding the System Libraries of the Combined Work.
1. Exception to Section 3 of the GNU GPL.
You may convey a covered work under sections 3 and 4 of this License
without being bound by section 3 of the GNU GPL.
2. Conveying Modified Versions.
If you modify a copy of the Library, and, in your modifications, a
facility refers to a function or data to be supplied by an Application
that uses the facility (other than as an argument passed when the
facility is invoked), then you may convey a copy of the modified
version:
a) under this License, provided that you make a good faith effort to
ensure that, in the event an Application does not supply the
function or data, the facility still operates, and performs
whatever part of its purpose remains meaningful, or
b) under the GNU GPL, with none of the additional permissions of
this License applicable to that copy.
3. Object Code Incorporating Material from Library Header Files.
The object code form of an Application may incorporate material from
a header file that is part of the Library. You may convey such object
code under terms of your choice, provided that, if the incorporated
material is not limited to numerical parameters, data structure
layouts and accessors, or small macros, inline functions and templates
(ten or fewer lines in length), you do both of the following:
a) Give prominent notice with each copy of the object code that the
Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the object code with a copy of the GNU GPL and this license
document.
4. Combined Works.
You may convey a Combined Work under terms of your choice that,
taken together, effectively do not restrict modification of the
portions of the Library contained in the Combined Work and reverse
engineering for debugging such modifications, if you also do each of
the following:
a) Give prominent notice with each copy of the Combined Work that
the Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the Combined Work with a copy of the GNU GPL and this license
document.
c) For a Combined Work that displays copyright notices during
execution, include the copyright notice for the Library among
these notices, as well as a reference directing the user to the
copies of the GNU GPL and this license document.
d) Do one of the following:
0) Convey the Minimal Corresponding Source under the terms of this
License, and the Corresponding Application Code in a form
suitable for, and under terms that permit, the user to
recombine or relink the Application with a modified version of
the Linked Version to produce a modified Combined Work, in the
manner specified by section 6 of the GNU GPL for conveying
Corresponding Source.
1) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (a) uses at run time
a copy of the Library already present on the user's computer
system, and (b) will operate properly with a modified version
of the Library that is interface-compatible with the Linked
Version.
e) Provide Installation Information, but only if you would otherwise
be required to provide such information under section 6 of the
GNU GPL, and only to the extent that such information is
necessary to install and execute a modified version of the
Combined Work produced by recombining or relinking the
Application with a modified version of the Linked Version. (If
you use option 4d0, the Installation Information must accompany
the Minimal Corresponding Source and Corresponding Application
Code. If you use option 4d1, you must provide the Installation
Information in the manner specified by section 6 of the GNU GPL
for conveying Corresponding Source.)
5. Combined Libraries.
You may place library facilities that are a work based on the
Library side by side in a single library together with other library
facilities that are not Applications and are not covered by this
License, and convey such a combined library under terms of your
choice, if you do both of the following:
a) Accompany the combined library with a copy of the same work based
on the Library, uncombined with any other library facilities,
conveyed under the terms of this License.
b) Give prominent notice with the combined library that part of it
is a work based on the Library, and explaining where to find the
accompanying uncombined form of the same work.
6. Revised Versions of the GNU Lesser General Public License.
The Free Software Foundation may publish revised and/or new versions
of the GNU Lesser General Public License from time to time. Such new
versions will be similar in spirit to the present version, but may
differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the
Library as you received it specifies that a certain numbered version
of the GNU Lesser General Public License "or any later version"
applies to it, you have the option of following the terms and
conditions either of that published version or of any later version
published by the Free Software Foundation. If the Library as you
received it does not specify a version number of the GNU Lesser
General Public License, you may choose any version of the GNU Lesser
General Public License ever published by the Free Software Foundation.
If the Library as you received it specifies that a proxy can decide
whether future versions of the GNU Lesser General Public License shall
apply, that proxy's public statement of acceptance of any version is
permanent authorization for you to choose that version for the
Library.
PROJECT := github.com/juju/errors
.PHONY: check-licence check-go check docs
check: check-licence check-go
go test $(PROJECT)/...
check-licence:
@(fgrep -rl "Licensed under the LGPLv3" --exclude *.s .;\
fgrep -rl "MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT" --exclude *.s .;\
find . -name "*.go") | sed -e 's,\./,,' | sort | uniq -u | \
xargs -I {} echo FAIL: licence missed: {}
check-go:
$(eval GOFMT := $(strip $(shell gofmt -l .| sed -e "s/^/ /g")))
@(if [ x$(GOFMT) != x"" ]; then \
echo go fmt is sad: $(GOFMT); \
exit 1; \
fi )
@(go tool vet -all -composites=false -copylocks=false .)
docs:
godoc2md github.com/juju/errors > README.md
sed -i '5i[\[GoDoc](https://godoc.org/github.com/juju/errors?status.svg)](https://godoc.org/github.com/juju/errors)' README.md
# errors
import "github.com/juju/errors"
[![GoDoc](https://godoc.org/github.com/juju/errors?status.svg)](https://godoc.org/github.com/juju/errors)
The juju/errors provides an easy way to annotate errors without losing the
orginal error context.
The exported `New` and `Errorf` functions are designed to replace the
`errors.New` and `fmt.Errorf` functions respectively. The same underlying
error is there, but the package also records the location at which the error
was created.
A primary use case for this library is to add extra context any time an
error is returned from a function.
if err := SomeFunc(); err != nil {
return err
}
This instead becomes:
if err := SomeFunc(); err != nil {
return errors.Trace(err)
}
which just records the file and line number of the Trace call, or
if err := SomeFunc(); err != nil {
return errors.Annotate(err, "more context")
}
which also adds an annotation to the error.
When you want to check to see if an error is of a particular type, a helper
function is normally exported by the package that returned the error, like the
`os` package does. The underlying cause of the error is available using the
`Cause` function.
os.IsNotExist(errors.Cause(err))
The result of the `Error()` call on an annotated error is the annotations joined
with colons, then the result of the `Error()` method for the underlying error
that was the cause.
err := errors.Errorf("original")
err = errors.Annotatef(err, "context")
err = errors.Annotatef(err, "more context")
err.Error() -> "more context: context: original"
Obviously recording the file, line and functions is not very useful if you
cannot get them back out again.
errors.ErrorStack(err)
will return something like:
first error
github.com/juju/errors/annotation_test.go:193:
github.com/juju/errors/annotation_test.go:194: annotation
github.com/juju/errors/annotation_test.go:195:
github.com/juju/errors/annotation_test.go:196: more context
github.com/juju/errors/annotation_test.go:197:
The first error was generated by an external system, so there was no location
associated. The second, fourth, and last lines were generated with Trace calls,
and the other two through Annotate.
Sometimes when responding to an error you want to return a more specific error
for the situation.
if err := FindField(field); err != nil {
return errors.Wrap(err, errors.NotFoundf(field))
}
This returns an error where the complete error stack is still available, and
`errors.Cause()` will return the `NotFound` error.
## func AlreadyExistsf
``` go
func AlreadyExistsf(format string, args ...interface{}) error
```
AlreadyExistsf returns an error which satisfies IsAlreadyExists().
## func Annotate
``` go
func Annotate(other error, message string) error
```
Annotate is used to add extra context to an existing error. The location of
the Annotate call is recorded with the annotations. The file, line and
function are also recorded.
For example:
if err := SomeFunc(); err != nil {
return errors.Annotate(err, "failed to frombulate")
}
## func Annotatef
``` go
func Annotatef(other error, format string, args ...interface{}) error
```
Annotatef is used to add extra context to an existing error. The location of
the Annotate call is recorded with the annotations. The file, line and
function are also recorded.
For example:
if err := SomeFunc(); err != nil {
return errors.Annotatef(err, "failed to frombulate the %s", arg)
}
## func BadRequestf
``` go
func BadRequestf(format string, args ...interface{}) error
```
BadRequestf returns an error which satisfies IsBadRequest().
## func Cause
``` go
func Cause(err error) error
```
Cause returns the cause of the given error. This will be either the
original error, or the result of a Wrap or Mask call.
Cause is the usual way to diagnose errors that may have been wrapped by
the other errors functions.
## func DeferredAnnotatef
``` go
func DeferredAnnotatef(err *error, format string, args ...interface{})
```
DeferredAnnotatef annotates the given error (when it is not nil) with the given
format string and arguments (like fmt.Sprintf). If *err is nil, DeferredAnnotatef
does nothing. This method is used in a defer statement in order to annotate any
resulting error with the same message.
For example:
defer DeferredAnnotatef(&err, "failed to frombulate the %s", arg)
## func Details
``` go
func Details(err error) string
```
Details returns information about the stack of errors wrapped by err, in
the format:
[{filename:99: error one} {otherfile:55: cause of error one}]
This is a terse alternative to ErrorStack as it returns a single line.
## func ErrorStack
``` go
func ErrorStack(err error) string
```
ErrorStack returns a string representation of the annotated error. If the
error passed as the parameter is not an annotated error, the result is
simply the result of the Error() method on that error.
If the error is an annotated error, a multi-line string is returned where
each line represents one entry in the annotation stack. The full filename
from the call stack is used in the output.
first error
github.com/juju/errors/annotation_test.go:193:
github.com/juju/errors/annotation_test.go:194: annotation
github.com/juju/errors/annotation_test.go:195:
github.com/juju/errors/annotation_test.go:196: more context
github.com/juju/errors/annotation_test.go:197:
## func Errorf
``` go
func Errorf(format string, args ...interface{}) error
```
Errorf creates a new annotated error and records the location that the
error is created. This should be a drop in replacement for fmt.Errorf.
For example:
return errors.Errorf("validation failed: %s", message)
## func Forbiddenf
``` go
func Forbiddenf(format string, args ...interface{}) error
```
Forbiddenf returns an error which satistifes IsForbidden()
## func IsAlreadyExists
``` go
func IsAlreadyExists(err error) bool
```
IsAlreadyExists reports whether the error was created with
AlreadyExistsf() or NewAlreadyExists().
## func IsBadRequest
``` go
func IsBadRequest(err error) bool
```
IsBadRequest reports whether err was created with BadRequestf() or
NewBadRequest().
## func IsForbidden
``` go
func IsForbidden(err error) bool
```
IsForbidden reports whether err was created with Forbiddenf() or
NewForbidden().
## func IsMethodNotAllowed
``` go
func IsMethodNotAllowed(err error) bool
```
IsMethodNotAllowed reports whether err was created with MethodNotAllowedf() or
NewMethodNotAllowed().
## func IsNotAssigned
``` go
func IsNotAssigned(err error) bool
```
IsNotAssigned reports whether err was created with NotAssignedf() or
NewNotAssigned().
## func IsNotFound
``` go
func IsNotFound(err error) bool
```
IsNotFound reports whether err was created with NotFoundf() or
NewNotFound().
## func IsNotImplemented
``` go
func IsNotImplemented(err error) bool
```
IsNotImplemented reports whether err was created with
NotImplementedf() or NewNotImplemented().
## func IsNotProvisioned
``` go
func IsNotProvisioned(err error) bool
```
IsNotProvisioned reports whether err was created with NotProvisionedf() or
NewNotProvisioned().
## func IsNotSupported
``` go
func IsNotSupported(err error) bool
```
IsNotSupported reports whether the error was created with
NotSupportedf() or NewNotSupported().
## func IsNotValid
``` go
func IsNotValid(err error) bool
```
IsNotValid reports whether the error was created with NotValidf() or
NewNotValid().
## func IsUnauthorized
``` go
func IsUnauthorized(err error) bool
```
IsUnauthorized reports whether err was created with Unauthorizedf() or
NewUnauthorized().
## func IsUserNotFound
``` go
func IsUserNotFound(err error) bool
```
IsUserNotFound reports whether err was created with UserNotFoundf() or
NewUserNotFound().
## func Mask
``` go
func Mask(other error) error
```
Mask hides the underlying error type, and records the location of the masking.
## func Maskf
``` go
func Maskf(other error, format string, args ...interface{}) error
```
Mask masks the given error with the given format string and arguments (like
fmt.Sprintf), returning a new error that maintains the error stack, but
hides the underlying error type. The error string still contains the full
annotations. If you want to hide the annotations, call Wrap.
## func MethodNotAllowedf
``` go
func MethodNotAllowedf(format string, args ...interface{}) error
```
MethodNotAllowedf returns an error which satisfies IsMethodNotAllowed().
## func New
``` go
func New(message string) error
```
New is a drop in replacement for the standard library errors module that records
the location that the error is created.
For example:
return errors.New("validation failed")
## func NewAlreadyExists
``` go
func NewAlreadyExists(err error, msg string) error
```
NewAlreadyExists returns an error which wraps err and satisfies
IsAlreadyExists().
## func NewBadRequest
``` go
func NewBadRequest(err error, msg string) error
```
NewBadRequest returns an error which wraps err that satisfies
IsBadRequest().
## func NewForbidden
``` go
func NewForbidden(err error, msg string) error
```
NewForbidden returns an error which wraps err that satisfies
IsForbidden().
## func NewMethodNotAllowed
``` go
func NewMethodNotAllowed(err error, msg string) error
```
NewMethodNotAllowed returns an error which wraps err that satisfies
IsMethodNotAllowed().
## func NewNotAssigned
``` go
func NewNotAssigned(err error, msg string) error
```
NewNotAssigned returns an error which wraps err that satisfies
IsNotAssigned().
## func NewNotFound
``` go
func NewNotFound(err error, msg string) error
```
NewNotFound returns an error which wraps err that satisfies
IsNotFound().
## func NewNotImplemented
``` go
func NewNotImplemented(err error, msg string) error
```
NewNotImplemented returns an error which wraps err and satisfies
IsNotImplemented().
## func NewNotProvisioned
``` go
func NewNotProvisioned(err error, msg string) error
```
NewNotProvisioned returns an error which wraps err that satisfies
IsNotProvisioned().
## func NewNotSupported
``` go
func NewNotSupported(err error, msg string) error
```
NewNotSupported returns an error which wraps err and satisfies
IsNotSupported().
## func NewNotValid
``` go
func NewNotValid(err error, msg string) error
```
NewNotValid returns an error which wraps err and satisfies IsNotValid().
## func NewUnauthorized
``` go
func NewUnauthorized(err error, msg string) error
```
NewUnauthorized returns an error which wraps err and satisfies
IsUnauthorized().
## func NewUserNotFound
``` go
func NewUserNotFound(err error, msg string) error
```
NewUserNotFound returns an error which wraps err and satisfies
IsUserNotFound().
## func NotAssignedf
``` go
func NotAssignedf(format string, args ...interface{}) error
```
NotAssignedf returns an error which satisfies IsNotAssigned().
## func NotFoundf
``` go
func NotFoundf(format string, args ...interface{}) error
```
NotFoundf returns an error which satisfies IsNotFound().
## func NotImplementedf
``` go
func NotImplementedf(format string, args ...interface{}) error
```
NotImplementedf returns an error which satisfies IsNotImplemented().
## func NotProvisionedf
``` go
func NotProvisionedf(format string, args ...interface{}) error
```
NotProvisionedf returns an error which satisfies IsNotProvisioned().
## func NotSupportedf
``` go
func NotSupportedf(format string, args ...interface{}) error
```
NotSupportedf returns an error which satisfies IsNotSupported().
## func NotValidf
``` go
func NotValidf(format string, args ...interface{}) error
```
NotValidf returns an error which satisfies IsNotValid().
## func Trace
``` go
func Trace(other error) error
```
Trace adds the location of the Trace call to the stack. The Cause of the
resulting error is the same as the error parameter. If the other error is
nil, the result will be nil.
For example:
if err := SomeFunc(); err != nil {
return errors.Trace(err)
}
## func Unauthorizedf
``` go
func Unauthorizedf(format string, args ...interface{}) error
```
Unauthorizedf returns an error which satisfies IsUnauthorized().
## func UserNotFoundf
``` go
func UserNotFoundf(format string, args ...interface{}) error
```
UserNotFoundf returns an error which satisfies IsUserNotFound().
## func Wrap
``` go
func Wrap(other, newDescriptive error) error
```
Wrap changes the Cause of the error. The location of the Wrap call is also
stored in the error stack.
For example:
if err := SomeFunc(); err != nil {
newErr := &packageError{"more context", private_value}
return errors.Wrap(err, newErr)
}
## func Wrapf
``` go
func Wrapf(other, newDescriptive error, format string, args ...interface{}) error
```
Wrapf changes the Cause of the error, and adds an annotation. The location
of the Wrap call is also stored in the error stack.
For example:
if err := SomeFunc(); err != nil {
return errors.Wrapf(err, simpleErrorType, "invalid value %q", value)
}
## type Err
``` go
type Err struct {
// contains filtered or unexported fields
}
```
Err holds a description of an error along with information about
where the error was created.
It may be embedded in custom error types to add extra information that
this errors package can understand.
### func NewErr
``` go
func NewErr(format string, args ...interface{}) Err
```
NewErr is used to return an Err for the purpose of embedding in other
structures. The location is not specified, and needs to be set with a call
to SetLocation.
For example:
type FooError struct {
errors.Err
code int
}
func NewFooError(code int) error {
err := &FooError{errors.NewErr("foo"), code}
err.SetLocation(1)
return err
}
### func NewErrWithCause
``` go
func NewErrWithCause(other error, format string, args ...interface{}) Err
```
NewErrWithCause is used to return an Err with cause by other error for the purpose of embedding in other
structures. The location is not specified, and needs to be set with a call
to SetLocation.
For example:
type FooError struct {
errors.Err
code int
}
func (e *FooError) Annotate(format string, args ...interface{}) error {
err := &FooError{errors.NewErrWithCause(e.Err, format, args...), e.code}
err.SetLocation(1)
return err
})
### func (\*Err) Cause
``` go
func (e *Err) Cause() error
```
The Cause of an error is the most recent error in the error stack that
meets one of these criteria: the original error that was raised; the new
error that was passed into the Wrap function; the most recently masked
error; or nil if the error itself is considered the Cause. Normally this
method is not invoked directly, but instead through the Cause stand alone
function.
### func (\*Err) Error
``` go
func (e *Err) Error() string
```
Error implements error.Error.
### func (\*Err) Format
``` go
func (e *Err) Format(s fmt.State, verb rune)
```
Format implements fmt.Formatter
When printing errors with %+v it also prints the stack trace.
%#v unsurprisingly will print the real underlying type.
### func (\*Err) Location
``` go
func (e *Err) Location() (filename string, line int)
```
Location is the file and line of where the error was most recently
created or annotated.
### func (\*Err) Message
``` go
func (e *Err) Message() string
```
Message returns the message stored with the most recent location. This is
the empty string if the most recent call was Trace, or the message stored
with Annotate or Mask.
### func (\*Err) SetLocation
``` go
func (e *Err) SetLocation(callDepth int)
```
SetLocation records the source location of the error at callDepth stack
frames above the call.
### func (\*Err) StackTrace
``` go
func (e *Err) StackTrace() []string
```
StackTrace returns one string for each location recorded in the stack of
errors. The first value is the originating error, with a line for each
other annotation or tracing of the error.
### func (\*Err) Underlying
``` go
func (e *Err) Underlying() error
```
Underlying returns the previous error in the error stack, if any. A client
should not ever really call this method. It is used to build the error
stack and should not be introspected by client calls. Or more
specifically, clients should not depend on anything but the `Cause` of an
error.
- - -
Generated by [godoc2md](http://godoc.org/github.com/davecheney/godoc2md)
\ No newline at end of file
github.com/juju/loggo git 8232ab8918d91c72af1a9fb94d3edbe31d88b790 2017-06-05T01:46:07Z
github.com/juju/testing git 72703b1e95eb8ce4737fd8a3d8496c6b0be280a6 2018-05-17T13:41:05Z
gopkg.in/check.v1 git 4f90aeace3a26ad7021961c297b22c42160c7b25 2016-01-05T16:49:36Z
gopkg.in/mgo.v2 git f2b6f6c918c452ad107eec89615f074e3bd80e33 2016-08-18T01:52:18Z
gopkg.in/yaml.v2 git 1be3d31502d6eabc0dd7ce5b0daab022e14a5538 2017-07-12T05:45:46Z
// Copyright 2013, 2014 Canonical Ltd.
// Licensed under the LGPLv3, see LICENCE file for details.
/*
Package errors provides an easy way to annotate errors without losing the
original error context.
The exported `New` and `Errorf` functions are designed to replace the
`errors.New` and `fmt.Errorf` functions respectively. The same underlying
error is there, but the package also records the location at which the error
was created.
A primary use case for this library is to add extra context any time an
error is returned from a function.
if err := SomeFunc(); err != nil {
return err
}
This instead becomes:
if err := SomeFunc(); err != nil {
return errors.Trace(err)
}
which just records the file and line number of the Trace call, or
if err := SomeFunc(); err != nil {
return errors.Annotate(err, "more context")
}
which also adds an annotation to the error.
When you want to check to see if an error is of a particular type, a helper
function is normally exported by the package that returned the error, like the
`os` package does. The underlying cause of the error is available using the
`Cause` function.
os.IsNotExist(errors.Cause(err))
The result of the `Error()` call on an annotated error is the annotations joined
with colons, then the result of the `Error()` method for the underlying error
that was the cause.
err := errors.Errorf("original")
err = errors.Annotatef(err, "context")
err = errors.Annotatef(err, "more context")
err.Error() -> "more context: context: original"
Obviously recording the file, line and functions is not very useful if you
cannot get them back out again.
errors.ErrorStack(err)
will return something like:
first error
github.com/juju/errors/annotation_test.go:193:
github.com/juju/errors/annotation_test.go:194: annotation
github.com/juju/errors/annotation_test.go:195:
github.com/juju/errors/annotation_test.go:196: more context
github.com/juju/errors/annotation_test.go:197:
The first error was generated by an external system, so there was no location
associated. The second, fourth, and last lines were generated with Trace calls,
and the other two through Annotate.
Sometimes when responding to an error you want to return a more specific error
for the situation.
if err := FindField(field); err != nil {
return errors.Wrap(err, errors.NotFoundf(field))
}
This returns an error where the complete error stack is still available, and
`errors.Cause()` will return the `NotFound` error.
*/
package errors
// Copyright 2014 Canonical Ltd.
// Licensed under the LGPLv3, see LICENCE file for details.
package errors
import (
"fmt"
"reflect"
"runtime"
)
// Err holds a description of an error along with information about
// where the error was created.
//
// It may be embedded in custom error types to add extra information that
// this errors package can understand.
type Err struct {
// message holds an annotation of the error.
message string
// cause holds the cause of the error as returned
// by the Cause method.
cause error
// previous holds the previous error in the error stack, if any.
previous error
// file and line hold the source code location where the error was
// created.
file string
line int
}
// NewErr is used to return an Err for the purpose of embedding in other
// structures. The location is not specified, and needs to be set with a call
// to SetLocation.
//
// For example:
// type FooError struct {
// errors.Err
// code int
// }
//
// func NewFooError(code int) error {
// err := &FooError{errors.NewErr("foo"), code}
// err.SetLocation(1)
// return err
// }
func NewErr(format string, args ...interface{}) Err {
return Err{
message: fmt.Sprintf(format, args...),
}
}
// NewErrWithCause is used to return an Err with cause by other error for the purpose of embedding in other
// structures. The location is not specified, and needs to be set with a call
// to SetLocation.
//
// For example:
// type FooError struct {
// errors.Err
// code int
// }
//
// func (e *FooError) Annotate(format string, args ...interface{}) error {
// err := &FooError{errors.NewErrWithCause(e.Err, format, args...), e.code}
// err.SetLocation(1)
// return err
// })
func NewErrWithCause(other error, format string, args ...interface{}) Err {
return Err{
message: fmt.Sprintf(format, args...),
cause: Cause(other),
previous: other,
}
}
// Location is the file and line of where the error was most recently
// created or annotated.
func (e *Err) Location() (filename string, line int) {
return e.file, e.line
}
// Underlying returns the previous error in the error stack, if any. A client
// should not ever really call this method. It is used to build the error
// stack and should not be introspected by client calls. Or more
// specifically, clients should not depend on anything but the `Cause` of an
// error.
func (e *Err) Underlying() error {
return e.previous
}
// Cause returns the most recent error in the error stack that
// meets one of these criteria: the original error that was raised; the new
// error that was passed into the Wrap function; the most recently masked
// error; or nil if the error itself is considered the Cause. Normally this
// method is not invoked directly, but instead through the Cause stand alone
// function.
func (e *Err) Cause() error {
return e.cause
}
// Message returns the message stored with the most recent location. This is
// the empty string if the most recent call was Trace, or the message stored
// with Annotate or Mask.
func (e *Err) Message() string {
return e.message
}
// Error implements error.Error.
func (e *Err) Error() string {
// We want to walk up the stack of errors showing the annotations
// as long as the cause is the same.
err := e.previous
if !sameError(Cause(err), e.cause) && e.cause != nil {
err = e.cause
}
switch {
case err == nil:
return e.message
case e.message == "":
return err.Error()
}
return fmt.Sprintf("%s: %v", e.message, err)
}
// Format implements fmt.Formatter
// When printing errors with %+v it also prints the stack trace.
// %#v unsurprisingly will print the real underlying type.
func (e *Err) Format(s fmt.State, verb rune) {
switch verb {
case 'v':
switch {
case s.Flag('+'):
fmt.Fprintf(s, "%s", ErrorStack(e))
return
case s.Flag('#'):
// avoid infinite recursion by wrapping e into a type
// that doesn't implement Formatter.
fmt.Fprintf(s, "%#v", (*unformatter)(e))
return
}
fallthrough
case 's':
fmt.Fprintf(s, "%s", e.Error())
case 'q':
fmt.Fprintf(s, "%q", e.Error())
default:
fmt.Fprintf(s, "%%!%c(%T=%s)", verb, e, e.Error())
}
}
// helper for Format
type unformatter Err
func (unformatter) Format() { /* break the fmt.Formatter interface */ }
// SetLocation records the source location of the error at callDepth stack
// frames above the call.
func (e *Err) SetLocation(callDepth int) {
_, file, line, _ := runtime.Caller(callDepth + 1)
e.file = trimSourcePath(file)
e.line = line
}
// StackTrace returns one string for each location recorded in the stack of
// errors. The first value is the originating error, with a line for each
// other annotation or tracing of the error.
func (e *Err) StackTrace() []string {
return errorStack(e)
}
// Ideally we'd have a way to check identity, but deep equals will do.
func sameError(e1, e2 error) bool {
return reflect.DeepEqual(e1, e2)
}
// Copyright 2014 Canonical Ltd.
// Licensed under the LGPLv3, see LICENCE file for details.
package errors
import (
"fmt"
)
// wrap is a helper to construct an *wrapper.
func wrap(err error, format, suffix string, args ...interface{}) Err {
newErr := Err{
message: fmt.Sprintf(format+suffix, args...),
previous: err,
}
newErr.SetLocation(2)
return newErr
}
// timeout represents an error on timeout.
type timeout struct {
Err
}
// Timeoutf returns an error which satisfies IsTimeout().
func Timeoutf(format string, args ...interface{}) error {
return &timeout{wrap(nil, format, " timeout", args...)}
}
// NewTimeout returns an error which wraps err that satisfies
// IsTimeout().
func NewTimeout(err error, msg string) error {
return &timeout{wrap(err, msg, "")}
}
// IsTimeout reports whether err was created with Timeoutf() or
// NewTimeout().
func IsTimeout(err error) bool {
err = Cause(err)
_, ok := err.(*timeout)
return ok
}
// notFound represents an error when something has not been found.
type notFound struct {
Err
}
// NotFoundf returns an error which satisfies IsNotFound().
func NotFoundf(format string, args ...interface{}) error {
return &notFound{wrap(nil, format, " not found", args...)}
}
// NewNotFound returns an error which wraps err that satisfies
// IsNotFound().
func NewNotFound(err error, msg string) error {
return &notFound{wrap(err, msg, "")}
}
// IsNotFound reports whether err was created with NotFoundf() or
// NewNotFound().
func IsNotFound(err error) bool {
err = Cause(err)
_, ok := err.(*notFound)
return ok
}
// userNotFound represents an error when an inexistent user is looked up.
type userNotFound struct {
Err
}
// UserNotFoundf returns an error which satisfies IsUserNotFound().
func UserNotFoundf(format string, args ...interface{}) error {
return &userNotFound{wrap(nil, format, " user not found", args...)}
}
// NewUserNotFound returns an error which wraps err and satisfies
// IsUserNotFound().
func NewUserNotFound(err error, msg string) error {
return &userNotFound{wrap(err, msg, "")}
}
// IsUserNotFound reports whether err was created with UserNotFoundf() or
// NewUserNotFound().
func IsUserNotFound(err error) bool {
err = Cause(err)
_, ok := err.(*userNotFound)
return ok
}
// unauthorized represents an error when an operation is unauthorized.
type unauthorized struct {
Err
}
// Unauthorizedf returns an error which satisfies IsUnauthorized().
func Unauthorizedf(format string, args ...interface{}) error {
return &unauthorized{wrap(nil, format, "", args...)}
}
// NewUnauthorized returns an error which wraps err and satisfies
// IsUnauthorized().
func NewUnauthorized(err error, msg string) error {
return &unauthorized{wrap(err, msg, "")}
}
// IsUnauthorized reports whether err was created with Unauthorizedf() or
// NewUnauthorized().
func IsUnauthorized(err error) bool {
err = Cause(err)
_, ok := err.(*unauthorized)
return ok
}
// notImplemented represents an error when something is not
// implemented.
type notImplemented struct {
Err
}
// NotImplementedf returns an error which satisfies IsNotImplemented().
func NotImplementedf(format string, args ...interface{}) error {
return &notImplemented{wrap(nil, format, " not implemented", args...)}
}
// NewNotImplemented returns an error which wraps err and satisfies
// IsNotImplemented().
func NewNotImplemented(err error, msg string) error {
return &notImplemented{wrap(err, msg, "")}
}
// IsNotImplemented reports whether err was created with
// NotImplementedf() or NewNotImplemented().
func IsNotImplemented(err error) bool {
err = Cause(err)
_, ok := err.(*notImplemented)
return ok
}
// alreadyExists represents and error when something already exists.
type alreadyExists struct {
Err
}
// AlreadyExistsf returns an error which satisfies IsAlreadyExists().
func AlreadyExistsf(format string, args ...interface{}) error {
return &alreadyExists{wrap(nil, format, " already exists", args...)}
}
// NewAlreadyExists returns an error which wraps err and satisfies
// IsAlreadyExists().
func NewAlreadyExists(err error, msg string) error {
return &alreadyExists{wrap(err, msg, "")}
}
// IsAlreadyExists reports whether the error was created with
// AlreadyExistsf() or NewAlreadyExists().
func IsAlreadyExists(err error) bool {
err = Cause(err)
_, ok := err.(*alreadyExists)
return ok
}
// notSupported represents an error when something is not supported.
type notSupported struct {
Err
}
// NotSupportedf returns an error which satisfies IsNotSupported().
func NotSupportedf(format string, args ...interface{}) error {
return &notSupported{wrap(nil, format, " not supported", args...)}
}
// NewNotSupported returns an error which wraps err and satisfies
// IsNotSupported().
func NewNotSupported(err error, msg string) error {
return &notSupported{wrap(err, msg, "")}
}
// IsNotSupported reports whether the error was created with
// NotSupportedf() or NewNotSupported().
func IsNotSupported(err error) bool {
err = Cause(err)
_, ok := err.(*notSupported)
return ok
}
// notValid represents an error when something is not valid.
type notValid struct {
Err
}
// NotValidf returns an error which satisfies IsNotValid().
func NotValidf(format string, args ...interface{}) error {
return &notValid{wrap(nil, format, " not valid", args...)}
}
// NewNotValid returns an error which wraps err and satisfies IsNotValid().
func NewNotValid(err error, msg string) error {
return &notValid{wrap(err, msg, "")}
}
// IsNotValid reports whether the error was created with NotValidf() or
// NewNotValid().
func IsNotValid(err error) bool {
err = Cause(err)
_, ok := err.(*notValid)
return ok
}
// notProvisioned represents an error when something is not yet provisioned.
type notProvisioned struct {
Err
}
// NotProvisionedf returns an error which satisfies IsNotProvisioned().
func NotProvisionedf(format string, args ...interface{}) error {
return &notProvisioned{wrap(nil, format, " not provisioned", args...)}
}
// NewNotProvisioned returns an error which wraps err that satisfies
// IsNotProvisioned().
func NewNotProvisioned(err error, msg string) error {
return &notProvisioned{wrap(err, msg, "")}
}
// IsNotProvisioned reports whether err was created with NotProvisionedf() or
// NewNotProvisioned().
func IsNotProvisioned(err error) bool {
err = Cause(err)
_, ok := err.(*notProvisioned)
return ok
}
// notAssigned represents an error when something is not yet assigned to
// something else.
type notAssigned struct {
Err
}
// NotAssignedf returns an error which satisfies IsNotAssigned().
func NotAssignedf(format string, args ...interface{}) error {
return &notAssigned{wrap(nil, format, " not assigned", args...)}
}
// NewNotAssigned returns an error which wraps err that satisfies
// IsNotAssigned().
func NewNotAssigned(err error, msg string) error {
return &notAssigned{wrap(err, msg, "")}
}
// IsNotAssigned reports whether err was created with NotAssignedf() or
// NewNotAssigned().
func IsNotAssigned(err error) bool {
err = Cause(err)
_, ok := err.(*notAssigned)
return ok
}
// badRequest represents an error when a request has bad parameters.
type badRequest struct {
Err
}
// BadRequestf returns an error which satisfies IsBadRequest().
func BadRequestf(format string, args ...interface{}) error {
return &badRequest{wrap(nil, format, "", args...)}
}
// NewBadRequest returns an error which wraps err that satisfies
// IsBadRequest().
func NewBadRequest(err error, msg string) error {
return &badRequest{wrap(err, msg, "")}
}
// IsBadRequest reports whether err was created with BadRequestf() or
// NewBadRequest().
func IsBadRequest(err error) bool {
err = Cause(err)
_, ok := err.(*badRequest)
return ok
}
// methodNotAllowed represents an error when an HTTP request
// is made with an inappropriate method.
type methodNotAllowed struct {
Err
}
// MethodNotAllowedf returns an error which satisfies IsMethodNotAllowed().
func MethodNotAllowedf(format string, args ...interface{}) error {
return &methodNotAllowed{wrap(nil, format, "", args...)}
}
// NewMethodNotAllowed returns an error which wraps err that satisfies
// IsMethodNotAllowed().
func NewMethodNotAllowed(err error, msg string) error {
return &methodNotAllowed{wrap(err, msg, "")}
}
// IsMethodNotAllowed reports whether err was created with MethodNotAllowedf() or
// NewMethodNotAllowed().
func IsMethodNotAllowed(err error) bool {
err = Cause(err)
_, ok := err.(*methodNotAllowed)
return ok
}
// forbidden represents an error when a request cannot be completed because of
// missing privileges
type forbidden struct {
Err
}
// Forbiddenf returns an error which satistifes IsForbidden()
func Forbiddenf(format string, args ...interface{}) error {
return &forbidden{wrap(nil, format, "", args...)}
}
// NewForbidden returns an error which wraps err that satisfies
// IsForbidden().
func NewForbidden(err error, msg string) error {
return &forbidden{wrap(err, msg, "")}
}
// IsForbidden reports whether err was created with Forbiddenf() or
// NewForbidden().
func IsForbidden(err error) bool {
err = Cause(err)
_, ok := err.(*forbidden)
return ok
}
// Copyright 2014 Canonical Ltd.
// Licensed under the LGPLv3, see LICENCE file for details.
package errors
import (
"fmt"
"strings"
)
// New is a drop in replacement for the standard library errors module that records
// the location that the error is created.
//
// For example:
// return errors.New("validation failed")
//
func New(message string) error {
err := &Err{message: message}
err.SetLocation(1)
return err
}
// Errorf creates a new annotated error and records the location that the
// error is created. This should be a drop in replacement for fmt.Errorf.
//
// For example:
// return errors.Errorf("validation failed: %s", message)
//
func Errorf(format string, args ...interface{}) error {
err := &Err{message: fmt.Sprintf(format, args...)}
err.SetLocation(1)
return err
}
// Trace adds the location of the Trace call to the stack. The Cause of the
// resulting error is the same as the error parameter. If the other error is
// nil, the result will be nil.
//
// For example:
// if err := SomeFunc(); err != nil {
// return errors.Trace(err)
// }
//
func Trace(other error) error {
if other == nil {
return nil
}
err := &Err{previous: other, cause: Cause(other)}
err.SetLocation(1)
return err
}
// Annotate is used to add extra context to an existing error. The location of
// the Annotate call is recorded with the annotations. The file, line and
// function are also recorded.
//
// For example:
// if err := SomeFunc(); err != nil {
// return errors.Annotate(err, "failed to frombulate")
// }
//
func Annotate(other error, message string) error {
if other == nil {
return nil
}
err := &Err{
previous: other,
cause: Cause(other),
message: message,
}
err.SetLocation(1)
return err
}
// Annotatef is used to add extra context to an existing error. The location of
// the Annotate call is recorded with the annotations. The file, line and
// function are also recorded.
//
// For example:
// if err := SomeFunc(); err != nil {
// return errors.Annotatef(err, "failed to frombulate the %s", arg)
// }
//
func Annotatef(other error, format string, args ...interface{}) error {
if other == nil {
return nil
}
err := &Err{
previous: other,
cause: Cause(other),
message: fmt.Sprintf(format, args...),
}
err.SetLocation(1)
return err
}
// DeferredAnnotatef annotates the given error (when it is not nil) with the given
// format string and arguments (like fmt.Sprintf). If *err is nil, DeferredAnnotatef
// does nothing. This method is used in a defer statement in order to annotate any
// resulting error with the same message.
//
// For example:
//
// defer DeferredAnnotatef(&err, "failed to frombulate the %s", arg)
//
func DeferredAnnotatef(err *error, format string, args ...interface{}) {
if *err == nil {
return
}
newErr := &Err{
message: fmt.Sprintf(format, args...),
cause: Cause(*err),
previous: *err,
}
newErr.SetLocation(1)
*err = newErr
}
// Wrap changes the Cause of the error. The location of the Wrap call is also
// stored in the error stack.
//
// For example:
// if err := SomeFunc(); err != nil {
// newErr := &packageError{"more context", private_value}
// return errors.Wrap(err, newErr)
// }
//
func Wrap(other, newDescriptive error) error {
err := &Err{
previous: other,
cause: newDescriptive,
}
err.SetLocation(1)
return err
}
// Wrapf changes the Cause of the error, and adds an annotation. The location
// of the Wrap call is also stored in the error stack.
//
// For example:
// if err := SomeFunc(); err != nil {
// return errors.Wrapf(err, simpleErrorType, "invalid value %q", value)
// }
//
func Wrapf(other, newDescriptive error, format string, args ...interface{}) error {
err := &Err{
message: fmt.Sprintf(format, args...),
previous: other,
cause: newDescriptive,
}
err.SetLocation(1)
return err
}
// Maskf masks the given error with the given format string and arguments (like
// fmt.Sprintf), returning a new error that maintains the error stack, but
// hides the underlying error type. The error string still contains the full
// annotations. If you want to hide the annotations, call Wrap.
func Maskf(other error, format string, args ...interface{}) error {
if other == nil {
return nil
}
err := &Err{
message: fmt.Sprintf(format, args...),
previous: other,
}
err.SetLocation(1)
return err
}
// Mask hides the underlying error type, and records the location of the masking.
func Mask(other error) error {
if other == nil {
return nil
}
err := &Err{
previous: other,
}
err.SetLocation(1)
return err
}
// Cause returns the cause of the given error. This will be either the
// original error, or the result of a Wrap or Mask call.
//
// Cause is the usual way to diagnose errors that may have been wrapped by
// the other errors functions.
func Cause(err error) error {
var diag error
if err, ok := err.(causer); ok {
diag = err.Cause()
}
if diag != nil {
return diag
}
return err
}
type causer interface {
Cause() error
}
type wrapper interface {
// Message returns the top level error message,
// not including the message from the Previous
// error.
Message() string
// Underlying returns the Previous error, or nil
// if there is none.
Underlying() error
}
type locationer interface {
Location() (string, int)
}
var (
_ wrapper = (*Err)(nil)
_ locationer = (*Err)(nil)
_ causer = (*Err)(nil)
)
// Details returns information about the stack of errors wrapped by err, in
// the format:
//
// [{filename:99: error one} {otherfile:55: cause of error one}]
//
// This is a terse alternative to ErrorStack as it returns a single line.
func Details(err error) string {
if err == nil {
return "[]"
}
var s []byte
s = append(s, '[')
for {
s = append(s, '{')
if err, ok := err.(locationer); ok {
file, line := err.Location()
if file != "" {
s = append(s, fmt.Sprintf("%s:%d", file, line)...)
s = append(s, ": "...)
}
}
if cerr, ok := err.(wrapper); ok {
s = append(s, cerr.Message()...)
err = cerr.Underlying()
} else {
s = append(s, err.Error()...)
err = nil
}
s = append(s, '}')
if err == nil {
break
}
s = append(s, ' ')
}
s = append(s, ']')
return string(s)
}
// ErrorStack returns a string representation of the annotated error. If the
// error passed as the parameter is not an annotated error, the result is
// simply the result of the Error() method on that error.
//
// If the error is an annotated error, a multi-line string is returned where
// each line represents one entry in the annotation stack. The full filename
// from the call stack is used in the output.
//
// first error
// github.com/juju/errors/annotation_test.go:193:
// github.com/juju/errors/annotation_test.go:194: annotation
// github.com/juju/errors/annotation_test.go:195:
// github.com/juju/errors/annotation_test.go:196: more context
// github.com/juju/errors/annotation_test.go:197:
func ErrorStack(err error) string {
return strings.Join(errorStack(err), "\n")
}
func errorStack(err error) []string {
if err == nil {
return nil
}
// We want the first error first
var lines []string
for {
var buff []byte
if err, ok := err.(locationer); ok {
file, line := err.Location()
// Strip off the leading GOPATH/src path elements.
file = trimSourcePath(file)
if file != "" {
buff = append(buff, fmt.Sprintf("%s:%d", file, line)...)
buff = append(buff, ": "...)
}
}
if cerr, ok := err.(wrapper); ok {
message := cerr.Message()
buff = append(buff, message...)
// If there is a cause for this error, and it is different to the cause
// of the underlying error, then output the error string in the stack trace.
var cause error
if err1, ok := err.(causer); ok {
cause = err1.Cause()
}
err = cerr.Underlying()
if cause != nil && !sameError(Cause(err), cause) {
if message != "" {
buff = append(buff, ": "...)
}
buff = append(buff, cause.Error()...)
}
} else {
buff = append(buff, err.Error()...)
err = nil
}
lines = append(lines, string(buff))
if err == nil {
break
}
}
// reverse the lines to get the original error, which was at the end of
// the list, back to the start.
var result []string
for i := len(lines); i > 0; i-- {
result = append(result, lines[i-1])
}
return result
}
// Copyright 2013, 2014 Canonical Ltd.
// Licensed under the LGPLv3, see LICENCE file for details.
package errors
import (
"go/build"
"os"
"path/filepath"
"strings"
"sync/atomic"
)
var trimValue atomic.Value
var trimDefault = filepath.Join(build.Default.GOPATH, "src") + string(os.PathSeparator)
func trimSourcePath(filename string) string {
prefix := trimDefault
if v := trimValue.Load(); v != nil {
prefix = v.(string)
}
return strings.TrimPrefix(filename, prefix)
}
func SetSourceTrimPrefix(s string) string {
previous := trimDefault
if v := trimValue.Load(); v != nil {
previous = v.(string)
}
trimValue.Store(s)
return previous
}
Copyright 2019 Ferdinand Neman
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
\ No newline at end of file
package antlr
type GroolParser struct {
}
package antlr
import (
"fmt"
"github.com/antlr/antlr4/runtime/Go/antlr"
"github.com/golang-collections/collections/stack"
"github.com/juju/errors"
"github.com/newm4n/grool/antlr/parser"
"github.com/newm4n/grool/model"
log "github.com/sirupsen/logrus"
"reflect"
"strconv"
"strings"
)
func NewGroolParserListener(kbase *model.KnowledgeBase) *GroolParserListener {
return &GroolParserListener{
Stack: stack.New(),
KnowledgeBase: kbase,
ParseErrors: make([]error, 0),
}
}
type GroolParserListener struct {
parser.BasegroolListener
ParseErrors []error
//RuleEntries map[string]*model.RuleEntry
KnowledgeBase *model.KnowledgeBase
Stack *stack.Stack
}
func (s *GroolParserListener) AddError(e error) {
log.Errorf("Got error : %v", e)
s.ParseErrors = append(s.ParseErrors, e)
}
// VisitTerminal is called when a terminal node is visited.
func (s *GroolParserListener) VisitTerminal(node antlr.TerminalNode) {}
// VisitErrorNode is called when an error node is visited.
func (s *GroolParserListener) VisitErrorNode(node antlr.ErrorNode) {}
// EnterEveryRule is called when any engine is entered.
func (s *GroolParserListener) EnterEveryRule(ctx antlr.ParserRuleContext) {}
// ExitEveryRule is called when any engine is exited.
func (s *GroolParserListener) ExitEveryRule(ctx antlr.ParserRuleContext) {}
// EnterRoot is called when production root is entered.
func (s *GroolParserListener) EnterRoot(ctx *parser.RootContext) {}
// ExitRoot is called when production root is exited.
func (s *GroolParserListener) ExitRoot(ctx *parser.RootContext) {}
// EnterRuleEntry is called when production ruleEntry is entered.
func (s *GroolParserListener) EnterRuleEntry(ctx *parser.RuleEntryContext) {
// return immediately when there's an error
if len(s.ParseErrors) > 0 {
return
}
entry := &model.RuleEntry{}
s.Stack.Push(entry)
}
// ExitRuleEntry is called when production ruleEntry is exited.
func (s *GroolParserListener) ExitRuleEntry(ctx *parser.RuleEntryContext) {
entry := s.Stack.Pop().(*model.RuleEntry)
// return immediately when there's an error
if len(s.ParseErrors) > 0 {
return
}
// check for duplicate engine.
if _, ok := s.KnowledgeBase.RuleEntries[entry.RuleName]; ok {
s.AddError(errors.Errorf("duplicate rule entry name '%s'", entry.RuleName))
return
}
// if everything ok, add the engine entry.
s.KnowledgeBase.RuleEntries[entry.RuleName] = entry
}
// EnterRuleName is called when production ruleName is entered.
func (s *GroolParserListener) EnterRuleName(ctx *parser.RuleNameContext) {
// return immediately when there's an error
if len(s.ParseErrors) > 0 {
return
}
ruleName := ctx.GetText()
entry := s.Stack.Peek().(*model.RuleEntry)
entry.RuleName = ruleName
}
// ExitRuleName is called when production ruleName is exited.
func (s *GroolParserListener) ExitRuleName(ctx *parser.RuleNameContext) {}
// EnterSalience is called when production salience is entered.
func (s *GroolParserListener) EnterSalience(ctx *parser.SalienceContext) {
// salience were set by the decimal literal
}
// ExitSalience is called when production salience is exited.
func (s *GroolParserListener) ExitSalience(ctx *parser.SalienceContext) {}
// EnterRuleDescription is called when production ruleDescription is entered.
func (s *GroolParserListener) EnterRuleDescription(ctx *parser.RuleDescriptionContext) {
// return immediately when there's an error
if len(s.ParseErrors) > 0 {
return
}
ruleDescription := ctx.GetText()
entry := s.Stack.Peek().(*model.RuleEntry)
entry.RuleDescription = ruleDescription
}
// ExitRuleDescription is called when production ruleDescription is exited.
func (s *GroolParserListener) ExitRuleDescription(ctx *parser.RuleDescriptionContext) {}
// EnterWhenScope is called when production whenScope is entered.
func (s *GroolParserListener) EnterWhenScope(ctx *parser.WhenScopeContext) {
// return immediately when there's an error
if len(s.ParseErrors) > 0 {
return
}
whenScope := &model.WhenScope{}
s.Stack.Push(whenScope)
}
// ExitWhenScope is called when production whenScope is exited.
func (s *GroolParserListener) ExitWhenScope(ctx *parser.WhenScopeContext) {
whenScope := s.Stack.Pop().(*model.WhenScope)
// return immediately when there's an error
if len(s.ParseErrors) > 0 {
return
}
ruleEntry := s.Stack.Peek().(*model.RuleEntry)
ruleEntry.WhenScope = whenScope
}
// EnterThenScope is called when production thenScope is entered.
func (s *GroolParserListener) EnterThenScope(ctx *parser.ThenScopeContext) {
// return immediately when there's an error
if len(s.ParseErrors) > 0 {
return
}
thenScope := &model.ThenScope{}
s.Stack.Push(thenScope)
}
// ExitThenScope is called when production thenScope is exited.
func (s *GroolParserListener) ExitThenScope(ctx *parser.ThenScopeContext) {
thenScope := s.Stack.Pop().(*model.ThenScope)
// return immediately when there's an error
if len(s.ParseErrors) > 0 {
return
}
ruleEntry := s.Stack.Peek().(*model.RuleEntry)
ruleEntry.ThenScope = thenScope
}
// EnterAssignExpressions is called when production assignExpressions is entered.
func (s *GroolParserListener) EnterAssignExpressions(ctx *parser.AssignExpressionsContext) {
// return immediately when there's an error
if len(s.ParseErrors) > 0 {
return
}
assigns := &model.AssignExpressions{
ExpressionList: make([]*model.AssignExpression, 0),
}
s.Stack.Push(assigns)
}
// ExitAssignExpressions is called when production assignExpressions is exited.
func (s *GroolParserListener) ExitAssignExpressions(ctx *parser.AssignExpressionsContext) {
assigns := s.Stack.Pop().(*model.AssignExpressions)
// return immediately when there's an error
if len(s.ParseErrors) > 0 {
return
}
thenScope := s.Stack.Peek().(*model.ThenScope)
thenScope.AssignExpressions = assigns
}
// EnterAssignExpression is called when production assignExpression is entered.
func (s *GroolParserListener) EnterAssignExpression(ctx *parser.AssignExpressionContext) {
// return immediately when there's an error
if len(s.ParseErrors) > 0 {
return
}
assign := &model.AssignExpression{}
s.Stack.Push(assign)
}
// ExitAssignExpression is called when production assignExpression is exited.
func (s *GroolParserListener) ExitAssignExpression(ctx *parser.AssignExpressionContext) {
assign := s.Stack.Pop().(*model.AssignExpression)
// return immediately when there's an error
if len(s.ParseErrors) > 0 {
return
}
assigns := s.Stack.Peek().(*model.AssignExpressions)
assigns.ExpressionList = append(assigns.ExpressionList, assign)
}
// EnterAssignment is called when production assignment is entered.
func (s *GroolParserListener) EnterAssignment(ctx *parser.AssignmentContext) {
// return immediately when there's an error
if len(s.ParseErrors) > 0 {
return
}
assignment := &model.Assignment{}
s.Stack.Push(assignment)
}
// ExitAssignment is called when production assignment is exited.
func (s *GroolParserListener) ExitAssignment(ctx *parser.AssignmentContext) {
assignment := s.Stack.Pop().(*model.Assignment)
// return immediately when there's an error
if len(s.ParseErrors) > 0 {
return
}
assign := s.Stack.Peek().(*model.AssignExpression)
assign.Assignment = assignment
}
// EnterExpression is called when production expression is entered.
func (s *GroolParserListener) EnterExpression(ctx *parser.ExpressionContext) {
// return immediately when there's an error
if len(s.ParseErrors) > 0 {
return
}
expression := &model.Expression{}
s.Stack.Push(expression)
}
// ExitExpression is called when production expression is exited.
func (s *GroolParserListener) ExitExpression(ctx *parser.ExpressionContext) {
expr := s.Stack.Pop().(*model.Expression)
// return immediately when there's an error
if len(s.ParseErrors) > 0 {
return
}
holder := s.Stack.Peek().(model.ExpressionHolder)
err := holder.AcceptExpression(expr)
if err != nil {
s.AddError(err)
}
}
// EnterPredicate is called when production predicate is entered.
func (s *GroolParserListener) EnterPredicate(ctx *parser.PredicateContext) {
// return immediately when there's an error
if len(s.ParseErrors) > 0 {
return
}
predicate := &model.Predicate{}
s.Stack.Push(predicate)
}
// ExitPredicate is called when production predicate is exited.
func (s *GroolParserListener) ExitPredicate(ctx *parser.PredicateContext) {
predicate := s.Stack.Pop().(*model.Predicate)
// return immediately when there's an error
if len(s.ParseErrors) > 0 {
return
}
expr := s.Stack.Peek().(*model.Expression)
expr.Predicate = predicate
}
// EnterExpressionAtom is called when production expressionAtom is entered.
func (s *GroolParserListener) EnterExpressionAtom(ctx *parser.ExpressionAtomContext) {
// return immediately when there's an error
if len(s.ParseErrors) > 0 {
return
}
exprAtom := &model.ExpressionAtom{
Text: ctx.GetText(),
}
s.Stack.Push(exprAtom)
}
// ExitExpressionAtom is called when production expressionAtom is exited.
func (s *GroolParserListener) ExitExpressionAtom(ctx *parser.ExpressionAtomContext) {
//fmt.Println(ctx.GetText())
exprAtom := s.Stack.Pop().(*model.ExpressionAtom)
// return immediately when there's an error
if len(s.ParseErrors) > 0 {
return
}
holder := s.Stack.Peek().(model.ExpressionAtomHolder)
err := holder.AcceptExpressionAtom(exprAtom)
if err != nil {
s.AddError(err)
}
}
// EnterMethodCall is called when production methodCall is entered.
func (s *GroolParserListener) EnterMethodCall(ctx *parser.MethodCallContext) {
// return immediately when there's an error
if len(s.ParseErrors) > 0 {
return
}
funcCall := &model.MethodCall{
MethodName: ctx.DOTTEDNAME().GetText(),
}
s.Stack.Push(funcCall)
}
// ExitMethodCall is called when production methodCall is exited.
func (s *GroolParserListener) ExitMethodCall(ctx *parser.MethodCallContext) {
methodCall := s.Stack.Pop().(*model.MethodCall)
// return immediately when there's an error
if len(s.ParseErrors) > 0 {
return
}
holder := s.Stack.Peek().(model.MethodCallHolder)
err := holder.AcceptMethodCall(methodCall)
if err != nil {
fmt.Printf("Got error %s\n", err)
s.AddError(err)
}
}
// EnterFunctionCall is called when production functionCall is entered.
func (s *GroolParserListener) EnterFunctionCall(ctx *parser.FunctionCallContext) {
// return immediately when there's an error
if len(s.ParseErrors) > 0 {
return
}
funcCall := &model.FunctionCall{
FunctionName: ctx.SIMPLENAME().GetText(),
}
s.Stack.Push(funcCall)
}
// ExitFunctionCall is called when production functionCall is exited.
func (s *GroolParserListener) ExitFunctionCall(ctx *parser.FunctionCallContext) {
funcCall := s.Stack.Pop().(*model.FunctionCall)
// return immediately when there's an error
if len(s.ParseErrors) > 0 {
return
}
holder := s.Stack.Peek().(model.FunctionCallHolder)
err := holder.AcceptFunctionCall(funcCall)
if err != nil {
s.AddError(err)
}
}
// EnterFunctionArgs is called when production functionArgs is entered.
func (s *GroolParserListener) EnterFunctionArgs(ctx *parser.FunctionArgsContext) {
// return immediately when there's an error
if len(s.ParseErrors) > 0 {
return
}
funcArg := &model.FunctionArgument{
Arguments: make([]*model.ArgumentHolder, 0),
}
s.Stack.Push(funcArg)
}
// ExitFunctionArgs is called when production functionArgs is exited.
func (s *GroolParserListener) ExitFunctionArgs(ctx *parser.FunctionArgsContext) {
funcArgs := s.Stack.Pop().(*model.FunctionArgument)
// return immediately when there's an error
if len(s.ParseErrors) > 0 {
return
}
argHolder := s.Stack.Peek().(model.FunctionArgumentHolder)
err := argHolder.AcceptFunctionArgument(funcArgs)
if err != nil {
s.AddError(err)
}
}
// EnterLogicalOperator is called when production logicalOperator is entered.
func (s *GroolParserListener) EnterLogicalOperator(ctx *parser.LogicalOperatorContext) {
}
// ExitLogicalOperator is called when production logicalOperator is exited.
func (s *GroolParserListener) ExitLogicalOperator(ctx *parser.LogicalOperatorContext) {
// return immediately when there's an error
if len(s.ParseErrors) > 0 {
return
}
expr := s.Stack.Peek().(*model.Expression)
if ctx.GetText() == "&&" {
expr.LogicalOperator = model.LogicalOperatorAnd
} else if ctx.GetText() == "||" {
expr.LogicalOperator = model.LogicalOperatorOr
} else {
s.AddError(errors.Errorf("unknown logical operator %s", ctx.GetText()))
}
}
// EnterVariable is called when production variable is entered.
func (s *GroolParserListener) EnterVariable(ctx *parser.VariableContext) {}
// ExitVariable is called when production variable is exited.
func (s *GroolParserListener) ExitVariable(ctx *parser.VariableContext) {
// return immediately when there's an error
if len(s.ParseErrors) > 0 {
return
}
varName := ctx.GetText()
//fmt.Println("Variable Name", varName)
// return immediately when there's an error
if len(s.ParseErrors) > 0 {
return
}
holder := s.Stack.Peek().(model.VariableHolder)
err := holder.AcceptVariable(varName)
if err != nil {
s.AddError(err)
}
}
// EnterMathOperator is called when production mathOperator is entered.
func (s *GroolParserListener) EnterMathOperator(ctx *parser.MathOperatorContext) {
}
// ExitMathOperator is called when production mathOperator is exited.
func (s *GroolParserListener) ExitMathOperator(ctx *parser.MathOperatorContext) {
// return immediately when there's an error
if len(s.ParseErrors) > 0 {
return
}
expr := s.Stack.Peek().(*model.ExpressionAtom)
if ctx.GetText() == "+" {
expr.MathOperator = model.MathOperatorPlus
} else if ctx.GetText() == "-" {
expr.MathOperator = model.MathOperatorMinus
} else if ctx.GetText() == "/" {
expr.MathOperator = model.MathOperatorDiv
} else if ctx.GetText() == "*" {
expr.MathOperator = model.MathOperatorMul
} else {
s.AddError(errors.Errorf("unknown mathematic operator %s", ctx.GetText()))
}
}
// EnterComparisonOperator is called when production comparisonOperator is entered.
func (s *GroolParserListener) EnterComparisonOperator(ctx *parser.ComparisonOperatorContext) {}
// ExitComparisonOperator is called when production comparisonOperator is exited.
func (s *GroolParserListener) ExitComparisonOperator(ctx *parser.ComparisonOperatorContext) {
// return immediately when there's an error
if len(s.ParseErrors) > 0 {
return
}
predicate := s.Stack.Peek().(*model.Predicate)
if ctx.GetText() == "==" {
predicate.ComparisonOperator = model.ComparisonOperatorEQ
} else if ctx.GetText() == "!=" {
predicate.ComparisonOperator = model.ComparisonOperatorNEQ
} else if ctx.GetText() == "<" {
predicate.ComparisonOperator = model.ComparisonOperatorLT
} else if ctx.GetText() == "<=" {
predicate.ComparisonOperator = model.ComparisonOperatorLTE
} else if ctx.GetText() == ">" {
predicate.ComparisonOperator = model.ComparisonOperatorGT
} else if ctx.GetText() == ">=" {
predicate.ComparisonOperator = model.ComparisonOperatorGTE
} else {
s.AddError(errors.Errorf("unknown comparison operator %s", ctx.GetText()))
}
}
// EnterConstant is called when production constant is entered.
func (s *GroolParserListener) EnterConstant(ctx *parser.ConstantContext) {
// return immediately when there's an error
if len(s.ParseErrors) > 0 {
return
}
cons := &model.Constant{}
s.Stack.Push(cons)
}
// ExitConstant is called when production constant is exited.
func (s *GroolParserListener) ExitConstant(ctx *parser.ConstantContext) {
cons := s.Stack.Pop().(*model.Constant)
// return immediately when there's an error
if len(s.ParseErrors) > 0 {
return
}
if ctx.NULL_LITERAL() != nil {
if ctx.NOT() != nil {
cons.ConstantValue = reflect.ValueOf("")
} else {
cons.ConstantValue = reflect.ValueOf(nil)
}
}
holder := s.Stack.Peek().(model.ConstantHolder)
err := holder.AcceptConstant(cons)
if err != nil {
s.AddError(err)
}
}
// EnterDecimalLiteral is called when production decimalLiteral is entered.
func (s *GroolParserListener) EnterDecimalLiteral(ctx *parser.DecimalLiteralContext) {}
// ExitDecimalLiteral is called when production decimalLiteral is exited.
func (s *GroolParserListener) ExitDecimalLiteral(ctx *parser.DecimalLiteralContext) {
// return immediately when there's an error
if len(s.ParseErrors) > 0 {
return
}
decHold := s.Stack.Peek().(model.DecimalHolder)
i64, err := strconv.ParseInt(ctx.GetText(), 10, 64)
if err != nil {
s.AddError(errors.Errorf("string to integer conversion error. literal is not a decimal '%s'", ctx.GetText()))
} else {
decHold.AcceptDecimal(i64)
//cons.ConstantValue = reflect.ValueOf(i64)
}
}
// EnterStringLiteral is called when production stringLiteral is entered.
func (s *GroolParserListener) EnterStringLiteral(ctx *parser.StringLiteralContext) {}
// ExitStringLiteral is called when production stringLiteral is exited.
func (s *GroolParserListener) ExitStringLiteral(ctx *parser.StringLiteralContext) {
// return immediately when there's an error
if len(s.ParseErrors) > 0 {
return
}
cons := s.Stack.Peek().(*model.Constant)
cons.ConstantValue = reflect.ValueOf(strings.Trim(ctx.GetText(), "\"'"))
}
// EnterBooleanLiteral is called when production booleanLiteral is entered.
func (s *GroolParserListener) EnterBooleanLiteral(ctx *parser.BooleanLiteralContext) {
}
// ExitBooleanLiteral is called when production booleanLiteral is exited.
func (s *GroolParserListener) ExitBooleanLiteral(ctx *parser.BooleanLiteralContext) {
// return immediately when there's an error
if len(s.ParseErrors) > 0 {
return
}
cons := s.Stack.Peek().(*model.Constant)
val := strings.ToLower(ctx.GetText())
if val == "true" {
cons.ConstantValue = reflect.ValueOf(true)
} else if val == "false" {
cons.ConstantValue = reflect.ValueOf(false)
} else {
s.AddError(errors.Errorf("unknown boolear literal '%s'", ctx.GetText()))
}
}
// EnterRealLiteral is called when production realLiteral is entered.
func (s *GroolParserListener) EnterRealLiteral(ctx *parser.RealLiteralContext) {}
// ExitRealLiteral is called when production realLiteral is exited.
func (s *GroolParserListener) ExitRealLiteral(ctx *parser.RealLiteralContext) {
// return immediately when there's an error
if len(s.ParseErrors) > 0 {
return
}
cons := s.Stack.Peek().(*model.Constant)
flo, err := strconv.ParseFloat(ctx.GetText(), 64)
if err != nil {
s.AddError(errors.Errorf("string to float conversion error. String is not real type '%s'", ctx.GetText()))
return
} else {
cons.ConstantValue = reflect.ValueOf(flo)
}
}
grammar grool;
// PARSER HERE
root
: ruleEntry* EOF
;
ruleEntry
: RULE ruleName ruleDescription? salience? LR_BRACE whenScope thenScope RR_BRACE
;
salience
: SALIENCE decimalLiteral
;
ruleName
: SIMPLENAME
;
ruleDescription
: DQUOTA_STRING | SQUOTA_STRING
;
whenScope
: WHEN expression
;
thenScope
: THEN assignExpressions
;
assignExpressions
: assignExpression+
;
assignExpression
: assignment SEMICOLON
| methodCall SEMICOLON
| functionCall SEMICOLON
;
assignment
: variable ASSIGN expression
;
expression
: expression logicalOperator expression
| LR_BRACKET expression logicalOperator expression RR_BRACKET
| predicate
;
predicate
: expressionAtom comparisonOperator expressionAtom
| expressionAtom
;
expressionAtom
: constant
| variable
| left=expressionAtom mathOperator right=expressionAtom
| LR_BRACKET left=expressionAtom mathOperator right=expressionAtom RR_BRACKET
| functionCall
| methodCall
;
methodCall
: DOTTEDNAME '(' functionArgs? ')'
;
functionCall
: SIMPLENAME '(' functionArgs? ')'
;
functionArgs
: (constant | variable | functionCall | methodCall | expression)
(
','
(constant | variable | functionCall | methodCall | expression)
)*
;
logicalOperator
: AND | OR
;
variable
: SIMPLENAME | DOTTEDNAME
;
mathOperator
: MUL | DIV | PLUS | MINUS
;
comparisonOperator
: GT | LT | GTE | LTE | EQUALS | NOTEQUALS
;
constant
: stringLiteral
| decimalLiteral
| '-' decimalLiteral
| booleanLiteral
| realLiteral
| NOT? NULL_LITERAL
;
decimalLiteral
: MINUS? DECIMAL_LITERAL
;
realLiteral
: MINUS? REAL_LITERAL
;
stringLiteral
: DQUOTA_STRING | SQUOTA_STRING
;
booleanLiteral
: TRUE | FALSE;
// LEXER HERE
fragment DEC_DIGIT : [0-9];
fragment A : [aA] ;
fragment B : [bB] ;
fragment C : [cC] ;
fragment D : [dD] ;
fragment E : [eE] ;
fragment F : [fF] ;
fragment G : [gG] ;
fragment H : [hH] ;
fragment I : [iI] ;
fragment J : [jJ] ;
fragment K : [kK] ;
fragment L : [lL] ;
fragment M : [mM] ;
fragment N : [nN] ;
fragment O : [oO] ;
fragment P : [pP] ;
fragment Q : [qQ] ;
fragment R : [rR] ;
fragment S : [sS] ;
fragment T : [tT] ;
fragment U : [uU] ;
fragment V : [vV] ;
fragment W : [wW] ;
fragment X : [xX] ;
fragment Y : [yY] ;
fragment Z : [zZ] ;
fragment EXPONENT_NUM_PART : 'E' '-'? DEC_DIGIT+;
RULE : R U L E ;
WHEN : W H E N ;
THEN : T H E N ;
AND : '&&' ;
OR : '||' ;
TRUE : T R U E ;
FALSE : F A L S E ;
NULL_LITERAL : N U L L ;
NOT : N O T ;
SALIENCE : S A L I E N C E ;
SIMPLENAME : [a-zA-Z] [a-zA-Z0-9]* ;
DOTTEDNAME : SIMPLENAME ( DOT SIMPLENAME )+ ;
PLUS : '+' ;
MINUS : '-' ;
DIV : '/' ;
MUL : '*' ;
EQUALS : '==' ;
ASSIGN : '=' ;
GT : '>' ;
LT : '<' ;
GTE : '>=' ;
LTE : '<=' ;
NOTEQUALS : '!=' ;
SEMICOLON : ';' ;
LR_BRACE : '{';
RR_BRACE : '}';
LR_BRACKET : '(';
RR_BRACKET : ')';
DOT : '.' ;
DQUOTA_STRING : '"' ( '\\'. | '""' | ~('"'| '\\') )* '"';
SQUOTA_STRING : '\'' ('\\'. | '\'\'' | ~('\'' | '\\'))* '\'';
DECIMAL_LITERAL : DEC_DIGIT+;
REAL_LITERAL : (DEC_DIGIT+)? '.' DEC_DIGIT+
| DEC_DIGIT+ '.' EXPONENT_NUM_PART
| (DEC_DIGIT+)? '.' (DEC_DIGIT+ EXPONENT_NUM_PART)
| DEC_DIGIT+ EXPONENT_NUM_PART
;
SPACE : [ \t\r\n]+ {l.Skip()}
;
COMMENT : '/*' .*? '*/' {l.Skip()}
;
LINE_COMMENT : '//' ~[\r\n]* {l.Skip()}
;
\ No newline at end of file
T__0=1
RULE=2
WHEN=3
THEN=4
AND=5
OR=6
TRUE=7
FALSE=8
NULL_LITERAL=9
NOT=10
SALIENCE=11
SIMPLENAME=12
DOTTEDNAME=13
PLUS=14
MINUS=15
DIV=16
MUL=17
EQUALS=18
ASSIGN=19
GT=20
LT=21
GTE=22
LTE=23
NOTEQUALS=24
SEMICOLON=25
LR_BRACE=26
RR_BRACE=27
LR_BRACKET=28
RR_BRACKET=29
DOT=30
DQUOTA_STRING=31
SQUOTA_STRING=32
DECIMAL_LITERAL=33
REAL_LITERAL=34
SPACE=35
COMMENT=36
LINE_COMMENT=37
','=1
'&&'=5
'||'=6
'+'=14
'-'=15
'/'=16
'*'=17
'=='=18
'='=19
'>'=20
'<'=21
'>='=22
'<='=23
'!='=24
';'=25
'{'=26
'}'=27
'('=28
')'=29
'.'=30
T__0=1
RULE=2
WHEN=3
THEN=4
AND=5
OR=6
TRUE=7
FALSE=8
NULL_LITERAL=9
NOT=10
SALIENCE=11
SIMPLENAME=12
DOTTEDNAME=13
PLUS=14
MINUS=15
DIV=16
MUL=17
EQUALS=18
ASSIGN=19
GT=20
LT=21
GTE=22
LTE=23
NOTEQUALS=24
SEMICOLON=25
LR_BRACE=26
RR_BRACE=27
LR_BRACKET=28
RR_BRACKET=29
DOT=30
DQUOTA_STRING=31
SQUOTA_STRING=32
DECIMAL_LITERAL=33
REAL_LITERAL=34
SPACE=35
COMMENT=36
LINE_COMMENT=37
','=1
'&&'=5
'||'=6
'+'=14
'-'=15
'/'=16
'*'=17
'=='=18
'='=19
'>'=20
'<'=21
'>='=22
'<='=23
'!='=24
';'=25
'{'=26
'}'=27
'('=28
')'=29
'.'=30
// Generated from grool.g4 by ANTLR 4.7.
package parser // grool
import "github.com/antlr/antlr4/runtime/Go/antlr"
// BasegroolListener is a complete listener for a parse tree produced by groolParser.
type BasegroolListener struct{}
var _ groolListener = &BasegroolListener{}
// VisitTerminal is called when a terminal node is visited.
func (s *BasegroolListener) VisitTerminal(node antlr.TerminalNode) {}
// VisitErrorNode is called when an error node is visited.
func (s *BasegroolListener) VisitErrorNode(node antlr.ErrorNode) {}
// EnterEveryRule is called when any rule is entered.
func (s *BasegroolListener) EnterEveryRule(ctx antlr.ParserRuleContext) {}
// ExitEveryRule is called when any rule is exited.
func (s *BasegroolListener) ExitEveryRule(ctx antlr.ParserRuleContext) {}
// EnterRoot is called when production root is entered.
func (s *BasegroolListener) EnterRoot(ctx *RootContext) {}
// ExitRoot is called when production root is exited.
func (s *BasegroolListener) ExitRoot(ctx *RootContext) {}
// EnterRuleEntry is called when production ruleEntry is entered.
func (s *BasegroolListener) EnterRuleEntry(ctx *RuleEntryContext) {}
// ExitRuleEntry is called when production ruleEntry is exited.
func (s *BasegroolListener) ExitRuleEntry(ctx *RuleEntryContext) {}
// EnterSalience is called when production salience is entered.
func (s *BasegroolListener) EnterSalience(ctx *SalienceContext) {}
// ExitSalience is called when production salience is exited.
func (s *BasegroolListener) ExitSalience(ctx *SalienceContext) {}
// EnterRuleName is called when production ruleName is entered.
func (s *BasegroolListener) EnterRuleName(ctx *RuleNameContext) {}
// ExitRuleName is called when production ruleName is exited.
func (s *BasegroolListener) ExitRuleName(ctx *RuleNameContext) {}
// EnterRuleDescription is called when production ruleDescription is entered.
func (s *BasegroolListener) EnterRuleDescription(ctx *RuleDescriptionContext) {}
// ExitRuleDescription is called when production ruleDescription is exited.
func (s *BasegroolListener) ExitRuleDescription(ctx *RuleDescriptionContext) {}
// EnterWhenScope is called when production whenScope is entered.
func (s *BasegroolListener) EnterWhenScope(ctx *WhenScopeContext) {}
// ExitWhenScope is called when production whenScope is exited.
func (s *BasegroolListener) ExitWhenScope(ctx *WhenScopeContext) {}
// EnterThenScope is called when production thenScope is entered.
func (s *BasegroolListener) EnterThenScope(ctx *ThenScopeContext) {}
// ExitThenScope is called when production thenScope is exited.
func (s *BasegroolListener) ExitThenScope(ctx *ThenScopeContext) {}
// EnterAssignExpressions is called when production assignExpressions is entered.
func (s *BasegroolListener) EnterAssignExpressions(ctx *AssignExpressionsContext) {}
// ExitAssignExpressions is called when production assignExpressions is exited.
func (s *BasegroolListener) ExitAssignExpressions(ctx *AssignExpressionsContext) {}
// EnterAssignExpression is called when production assignExpression is entered.
func (s *BasegroolListener) EnterAssignExpression(ctx *AssignExpressionContext) {}
// ExitAssignExpression is called when production assignExpression is exited.
func (s *BasegroolListener) ExitAssignExpression(ctx *AssignExpressionContext) {}
// EnterAssignment is called when production assignment is entered.
func (s *BasegroolListener) EnterAssignment(ctx *AssignmentContext) {}
// ExitAssignment is called when production assignment is exited.
func (s *BasegroolListener) ExitAssignment(ctx *AssignmentContext) {}
// EnterExpression is called when production expression is entered.
func (s *BasegroolListener) EnterExpression(ctx *ExpressionContext) {}
// ExitExpression is called when production expression is exited.
func (s *BasegroolListener) ExitExpression(ctx *ExpressionContext) {}
// EnterPredicate is called when production predicate is entered.
func (s *BasegroolListener) EnterPredicate(ctx *PredicateContext) {}
// ExitPredicate is called when production predicate is exited.
func (s *BasegroolListener) ExitPredicate(ctx *PredicateContext) {}
// EnterExpressionAtom is called when production expressionAtom is entered.
func (s *BasegroolListener) EnterExpressionAtom(ctx *ExpressionAtomContext) {}
// ExitExpressionAtom is called when production expressionAtom is exited.
func (s *BasegroolListener) ExitExpressionAtom(ctx *ExpressionAtomContext) {}
// EnterMethodCall is called when production methodCall is entered.
func (s *BasegroolListener) EnterMethodCall(ctx *MethodCallContext) {}
// ExitMethodCall is called when production methodCall is exited.
func (s *BasegroolListener) ExitMethodCall(ctx *MethodCallContext) {}
// EnterFunctionCall is called when production functionCall is entered.
func (s *BasegroolListener) EnterFunctionCall(ctx *FunctionCallContext) {}
// ExitFunctionCall is called when production functionCall is exited.
func (s *BasegroolListener) ExitFunctionCall(ctx *FunctionCallContext) {}
// EnterFunctionArgs is called when production functionArgs is entered.
func (s *BasegroolListener) EnterFunctionArgs(ctx *FunctionArgsContext) {}
// ExitFunctionArgs is called when production functionArgs is exited.
func (s *BasegroolListener) ExitFunctionArgs(ctx *FunctionArgsContext) {}
// EnterLogicalOperator is called when production logicalOperator is entered.
func (s *BasegroolListener) EnterLogicalOperator(ctx *LogicalOperatorContext) {}
// ExitLogicalOperator is called when production logicalOperator is exited.
func (s *BasegroolListener) ExitLogicalOperator(ctx *LogicalOperatorContext) {}
// EnterVariable is called when production variable is entered.
func (s *BasegroolListener) EnterVariable(ctx *VariableContext) {}
// ExitVariable is called when production variable is exited.
func (s *BasegroolListener) ExitVariable(ctx *VariableContext) {}
// EnterMathOperator is called when production mathOperator is entered.
func (s *BasegroolListener) EnterMathOperator(ctx *MathOperatorContext) {}
// ExitMathOperator is called when production mathOperator is exited.
func (s *BasegroolListener) ExitMathOperator(ctx *MathOperatorContext) {}
// EnterComparisonOperator is called when production comparisonOperator is entered.
func (s *BasegroolListener) EnterComparisonOperator(ctx *ComparisonOperatorContext) {}
// ExitComparisonOperator is called when production comparisonOperator is exited.
func (s *BasegroolListener) ExitComparisonOperator(ctx *ComparisonOperatorContext) {}
// EnterConstant is called when production constant is entered.
func (s *BasegroolListener) EnterConstant(ctx *ConstantContext) {}
// ExitConstant is called when production constant is exited.
func (s *BasegroolListener) ExitConstant(ctx *ConstantContext) {}
// EnterDecimalLiteral is called when production decimalLiteral is entered.
func (s *BasegroolListener) EnterDecimalLiteral(ctx *DecimalLiteralContext) {}
// ExitDecimalLiteral is called when production decimalLiteral is exited.
func (s *BasegroolListener) ExitDecimalLiteral(ctx *DecimalLiteralContext) {}
// EnterRealLiteral is called when production realLiteral is entered.
func (s *BasegroolListener) EnterRealLiteral(ctx *RealLiteralContext) {}
// ExitRealLiteral is called when production realLiteral is exited.
func (s *BasegroolListener) ExitRealLiteral(ctx *RealLiteralContext) {}
// EnterStringLiteral is called when production stringLiteral is entered.
func (s *BasegroolListener) EnterStringLiteral(ctx *StringLiteralContext) {}
// ExitStringLiteral is called when production stringLiteral is exited.
func (s *BasegroolListener) ExitStringLiteral(ctx *StringLiteralContext) {}
// EnterBooleanLiteral is called when production booleanLiteral is entered.
func (s *BasegroolListener) EnterBooleanLiteral(ctx *BooleanLiteralContext) {}
// ExitBooleanLiteral is called when production booleanLiteral is exited.
func (s *BasegroolListener) ExitBooleanLiteral(ctx *BooleanLiteralContext) {}
// Generated from grool.g4 by ANTLR 4.7.
package parser
import (
"fmt"
"unicode"
"github.com/antlr/antlr4/runtime/Go/antlr"
)
// Suppress unused import error
var _ = fmt.Printf
var _ = unicode.IsLetter
var serializedLexerAtn = []uint16{
3, 24715, 42794, 33075, 47597, 16764, 15335, 30598, 22884, 2, 39, 409,
8, 1, 4, 2, 9, 2, 4, 3, 9, 3, 4, 4, 9, 4, 4, 5, 9, 5, 4, 6, 9, 6, 4, 7,
9, 7, 4, 8, 9, 8, 4, 9, 9, 9, 4, 10, 9, 10, 4, 11, 9, 11, 4, 12, 9, 12,
4, 13, 9, 13, 4, 14, 9, 14, 4, 15, 9, 15, 4, 16, 9, 16, 4, 17, 9, 17, 4,
18, 9, 18, 4, 19, 9, 19, 4, 20, 9, 20, 4, 21, 9, 21, 4, 22, 9, 22, 4, 23,
9, 23, 4, 24, 9, 24, 4, 25, 9, 25, 4, 26, 9, 26, 4, 27, 9, 27, 4, 28, 9,
28, 4, 29, 9, 29, 4, 30, 9, 30, 4, 31, 9, 31, 4, 32, 9, 32, 4, 33, 9, 33,
4, 34, 9, 34, 4, 35, 9, 35, 4, 36, 9, 36, 4, 37, 9, 37, 4, 38, 9, 38, 4,
39, 9, 39, 4, 40, 9, 40, 4, 41, 9, 41, 4, 42, 9, 42, 4, 43, 9, 43, 4, 44,
9, 44, 4, 45, 9, 45, 4, 46, 9, 46, 4, 47, 9, 47, 4, 48, 9, 48, 4, 49, 9,
49, 4, 50, 9, 50, 4, 51, 9, 51, 4, 52, 9, 52, 4, 53, 9, 53, 4, 54, 9, 54,
4, 55, 9, 55, 4, 56, 9, 56, 4, 57, 9, 57, 4, 58, 9, 58, 4, 59, 9, 59, 4,
60, 9, 60, 4, 61, 9, 61, 4, 62, 9, 62, 4, 63, 9, 63, 4, 64, 9, 64, 4, 65,
9, 65, 4, 66, 9, 66, 3, 2, 3, 2, 3, 3, 3, 3, 3, 4, 3, 4, 3, 5, 3, 5, 3,
6, 3, 6, 3, 7, 3, 7, 3, 8, 3, 8, 3, 9, 3, 9, 3, 10, 3, 10, 3, 11, 3, 11,
3, 12, 3, 12, 3, 13, 3, 13, 3, 14, 3, 14, 3, 15, 3, 15, 3, 16, 3, 16, 3,
17, 3, 17, 3, 18, 3, 18, 3, 19, 3, 19, 3, 20, 3, 20, 3, 21, 3, 21, 3, 22,
3, 22, 3, 23, 3, 23, 3, 24, 3, 24, 3, 25, 3, 25, 3, 26, 3, 26, 3, 27, 3,
27, 3, 28, 3, 28, 3, 29, 3, 29, 3, 30, 3, 30, 5, 30, 192, 10, 30, 3, 30,
6, 30, 195, 10, 30, 13, 30, 14, 30, 196, 3, 31, 3, 31, 3, 31, 3, 31, 3,
31, 3, 32, 3, 32, 3, 32, 3, 32, 3, 32, 3, 33, 3, 33, 3, 33, 3, 33, 3, 33,
3, 34, 3, 34, 3, 34, 3, 35, 3, 35, 3, 35, 3, 36, 3, 36, 3, 36, 3, 36, 3,
36, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 37, 3, 38, 3, 38, 3, 38, 3, 38,
3, 38, 3, 39, 3, 39, 3, 39, 3, 39, 3, 40, 3, 40, 3, 40, 3, 40, 3, 40, 3,
40, 3, 40, 3, 40, 3, 40, 3, 41, 3, 41, 7, 41, 251, 10, 41, 12, 41, 14,
41, 254, 11, 41, 3, 42, 3, 42, 3, 42, 3, 42, 6, 42, 260, 10, 42, 13, 42,
14, 42, 261, 3, 43, 3, 43, 3, 44, 3, 44, 3, 45, 3, 45, 3, 46, 3, 46, 3,
47, 3, 47, 3, 47, 3, 48, 3, 48, 3, 49, 3, 49, 3, 50, 3, 50, 3, 51, 3, 51,
3, 51, 3, 52, 3, 52, 3, 52, 3, 53, 3, 53, 3, 53, 3, 54, 3, 54, 3, 55, 3,
55, 3, 56, 3, 56, 3, 57, 3, 57, 3, 58, 3, 58, 3, 59, 3, 59, 3, 60, 3, 60,
3, 60, 3, 60, 3, 60, 3, 60, 7, 60, 308, 10, 60, 12, 60, 14, 60, 311, 11,
60, 3, 60, 3, 60, 3, 61, 3, 61, 3, 61, 3, 61, 3, 61, 3, 61, 7, 61, 321,
10, 61, 12, 61, 14, 61, 324, 11, 61, 3, 61, 3, 61, 3, 62, 6, 62, 329, 10,
62, 13, 62, 14, 62, 330, 3, 63, 6, 63, 334, 10, 63, 13, 63, 14, 63, 335,
5, 63, 338, 10, 63, 3, 63, 3, 63, 6, 63, 342, 10, 63, 13, 63, 14, 63, 343,
3, 63, 6, 63, 347, 10, 63, 13, 63, 14, 63, 348, 3, 63, 3, 63, 3, 63, 3,
63, 6, 63, 355, 10, 63, 13, 63, 14, 63, 356, 5, 63, 359, 10, 63, 3, 63,
3, 63, 6, 63, 363, 10, 63, 13, 63, 14, 63, 364, 3, 63, 3, 63, 3, 63, 6,
63, 370, 10, 63, 13, 63, 14, 63, 371, 3, 63, 3, 63, 5, 63, 376, 10, 63,
3, 64, 6, 64, 379, 10, 64, 13, 64, 14, 64, 380, 3, 64, 3, 64, 3, 65, 3,
65, 3, 65, 3, 65, 7, 65, 389, 10, 65, 12, 65, 14, 65, 392, 11, 65, 3, 65,
3, 65, 3, 65, 3, 65, 3, 65, 3, 66, 3, 66, 3, 66, 3, 66, 7, 66, 403, 10,
66, 12, 66, 14, 66, 406, 11, 66, 3, 66, 3, 66, 3, 390, 2, 67, 3, 3, 5,
2, 7, 2, 9, 2, 11, 2, 13, 2, 15, 2, 17, 2, 19, 2, 21, 2, 23, 2, 25, 2,
27, 2, 29, 2, 31, 2, 33, 2, 35, 2, 37, 2, 39, 2, 41, 2, 43, 2, 45, 2, 47,
2, 49, 2, 51, 2, 53, 2, 55, 2, 57, 2, 59, 2, 61, 4, 63, 5, 65, 6, 67, 7,
69, 8, 71, 9, 73, 10, 75, 11, 77, 12, 79, 13, 81, 14, 83, 15, 85, 16, 87,
17, 89, 18, 91, 19, 93, 20, 95, 21, 97, 22, 99, 23, 101, 24, 103, 25, 105,
26, 107, 27, 109, 28, 111, 29, 113, 30, 115, 31, 117, 32, 119, 33, 121,
34, 123, 35, 125, 36, 127, 37, 129, 38, 131, 39, 3, 2, 35, 3, 2, 50, 59,
4, 2, 67, 67, 99, 99, 4, 2, 68, 68, 100, 100, 4, 2, 69, 69, 101, 101, 4,
2, 70, 70, 102, 102, 4, 2, 71, 71, 103, 103, 4, 2, 72, 72, 104, 104, 4,
2, 73, 73, 105, 105, 4, 2, 74, 74, 106, 106, 4, 2, 75, 75, 107, 107, 4,
2, 76, 76, 108, 108, 4, 2, 77, 77, 109, 109, 4, 2, 78, 78, 110, 110, 4,
2, 79, 79, 111, 111, 4, 2, 80, 80, 112, 112, 4, 2, 81, 81, 113, 113, 4,
2, 82, 82, 114, 114, 4, 2, 83, 83, 115, 115, 4, 2, 84, 84, 116, 116, 4,
2, 85, 85, 117, 117, 4, 2, 86, 86, 118, 118, 4, 2, 87, 87, 119, 119, 4,
2, 88, 88, 120, 120, 4, 2, 89, 89, 121, 121, 4, 2, 90, 90, 122, 122, 4,
2, 91, 91, 123, 123, 4, 2, 92, 92, 124, 124, 4, 2, 67, 92, 99, 124, 5,
2, 50, 59, 67, 92, 99, 124, 4, 2, 36, 36, 94, 94, 4, 2, 41, 41, 94, 94,
5, 2, 11, 12, 15, 15, 34, 34, 4, 2, 12, 12, 15, 15, 2, 405, 2, 3, 3, 2,
2, 2, 2, 61, 3, 2, 2, 2, 2, 63, 3, 2, 2, 2, 2, 65, 3, 2, 2, 2, 2, 67, 3,
2, 2, 2, 2, 69, 3, 2, 2, 2, 2, 71, 3, 2, 2, 2, 2, 73, 3, 2, 2, 2, 2, 75,
3, 2, 2, 2, 2, 77, 3, 2, 2, 2, 2, 79, 3, 2, 2, 2, 2, 81, 3, 2, 2, 2, 2,
83, 3, 2, 2, 2, 2, 85, 3, 2, 2, 2, 2, 87, 3, 2, 2, 2, 2, 89, 3, 2, 2, 2,
2, 91, 3, 2, 2, 2, 2, 93, 3, 2, 2, 2, 2, 95, 3, 2, 2, 2, 2, 97, 3, 2, 2,
2, 2, 99, 3, 2, 2, 2, 2, 101, 3, 2, 2, 2, 2, 103, 3, 2, 2, 2, 2, 105, 3,
2, 2, 2, 2, 107, 3, 2, 2, 2, 2, 109, 3, 2, 2, 2, 2, 111, 3, 2, 2, 2, 2,
113, 3, 2, 2, 2, 2, 115, 3, 2, 2, 2, 2, 117, 3, 2, 2, 2, 2, 119, 3, 2,
2, 2, 2, 121, 3, 2, 2, 2, 2, 123, 3, 2, 2, 2, 2, 125, 3, 2, 2, 2, 2, 127,
3, 2, 2, 2, 2, 129, 3, 2, 2, 2, 2, 131, 3, 2, 2, 2, 3, 133, 3, 2, 2, 2,
5, 135, 3, 2, 2, 2, 7, 137, 3, 2, 2, 2, 9, 139, 3, 2, 2, 2, 11, 141, 3,
2, 2, 2, 13, 143, 3, 2, 2, 2, 15, 145, 3, 2, 2, 2, 17, 147, 3, 2, 2, 2,
19, 149, 3, 2, 2, 2, 21, 151, 3, 2, 2, 2, 23, 153, 3, 2, 2, 2, 25, 155,
3, 2, 2, 2, 27, 157, 3, 2, 2, 2, 29, 159, 3, 2, 2, 2, 31, 161, 3, 2, 2,
2, 33, 163, 3, 2, 2, 2, 35, 165, 3, 2, 2, 2, 37, 167, 3, 2, 2, 2, 39, 169,
3, 2, 2, 2, 41, 171, 3, 2, 2, 2, 43, 173, 3, 2, 2, 2, 45, 175, 3, 2, 2,
2, 47, 177, 3, 2, 2, 2, 49, 179, 3, 2, 2, 2, 51, 181, 3, 2, 2, 2, 53, 183,
3, 2, 2, 2, 55, 185, 3, 2, 2, 2, 57, 187, 3, 2, 2, 2, 59, 189, 3, 2, 2,
2, 61, 198, 3, 2, 2, 2, 63, 203, 3, 2, 2, 2, 65, 208, 3, 2, 2, 2, 67, 213,
3, 2, 2, 2, 69, 216, 3, 2, 2, 2, 71, 219, 3, 2, 2, 2, 73, 224, 3, 2, 2,
2, 75, 230, 3, 2, 2, 2, 77, 235, 3, 2, 2, 2, 79, 239, 3, 2, 2, 2, 81, 248,
3, 2, 2, 2, 83, 255, 3, 2, 2, 2, 85, 263, 3, 2, 2, 2, 87, 265, 3, 2, 2,
2, 89, 267, 3, 2, 2, 2, 91, 269, 3, 2, 2, 2, 93, 271, 3, 2, 2, 2, 95, 274,
3, 2, 2, 2, 97, 276, 3, 2, 2, 2, 99, 278, 3, 2, 2, 2, 101, 280, 3, 2, 2,
2, 103, 283, 3, 2, 2, 2, 105, 286, 3, 2, 2, 2, 107, 289, 3, 2, 2, 2, 109,
291, 3, 2, 2, 2, 111, 293, 3, 2, 2, 2, 113, 295, 3, 2, 2, 2, 115, 297,
3, 2, 2, 2, 117, 299, 3, 2, 2, 2, 119, 301, 3, 2, 2, 2, 121, 314, 3, 2,
2, 2, 123, 328, 3, 2, 2, 2, 125, 375, 3, 2, 2, 2, 127, 378, 3, 2, 2, 2,
129, 384, 3, 2, 2, 2, 131, 398, 3, 2, 2, 2, 133, 134, 7, 46, 2, 2, 134,
4, 3, 2, 2, 2, 135, 136, 9, 2, 2, 2, 136, 6, 3, 2, 2, 2, 137, 138, 9, 3,
2, 2, 138, 8, 3, 2, 2, 2, 139, 140, 9, 4, 2, 2, 140, 10, 3, 2, 2, 2, 141,
142, 9, 5, 2, 2, 142, 12, 3, 2, 2, 2, 143, 144, 9, 6, 2, 2, 144, 14, 3,
2, 2, 2, 145, 146, 9, 7, 2, 2, 146, 16, 3, 2, 2, 2, 147, 148, 9, 8, 2,
2, 148, 18, 3, 2, 2, 2, 149, 150, 9, 9, 2, 2, 150, 20, 3, 2, 2, 2, 151,
152, 9, 10, 2, 2, 152, 22, 3, 2, 2, 2, 153, 154, 9, 11, 2, 2, 154, 24,
3, 2, 2, 2, 155, 156, 9, 12, 2, 2, 156, 26, 3, 2, 2, 2, 157, 158, 9, 13,
2, 2, 158, 28, 3, 2, 2, 2, 159, 160, 9, 14, 2, 2, 160, 30, 3, 2, 2, 2,
161, 162, 9, 15, 2, 2, 162, 32, 3, 2, 2, 2, 163, 164, 9, 16, 2, 2, 164,
34, 3, 2, 2, 2, 165, 166, 9, 17, 2, 2, 166, 36, 3, 2, 2, 2, 167, 168, 9,
18, 2, 2, 168, 38, 3, 2, 2, 2, 169, 170, 9, 19, 2, 2, 170, 40, 3, 2, 2,
2, 171, 172, 9, 20, 2, 2, 172, 42, 3, 2, 2, 2, 173, 174, 9, 21, 2, 2, 174,
44, 3, 2, 2, 2, 175, 176, 9, 22, 2, 2, 176, 46, 3, 2, 2, 2, 177, 178, 9,
23, 2, 2, 178, 48, 3, 2, 2, 2, 179, 180, 9, 24, 2, 2, 180, 50, 3, 2, 2,
2, 181, 182, 9, 25, 2, 2, 182, 52, 3, 2, 2, 2, 183, 184, 9, 26, 2, 2, 184,
54, 3, 2, 2, 2, 185, 186, 9, 27, 2, 2, 186, 56, 3, 2, 2, 2, 187, 188, 9,
28, 2, 2, 188, 58, 3, 2, 2, 2, 189, 191, 7, 71, 2, 2, 190, 192, 7, 47,
2, 2, 191, 190, 3, 2, 2, 2, 191, 192, 3, 2, 2, 2, 192, 194, 3, 2, 2, 2,
193, 195, 5, 5, 3, 2, 194, 193, 3, 2, 2, 2, 195, 196, 3, 2, 2, 2, 196,
194, 3, 2, 2, 2, 196, 197, 3, 2, 2, 2, 197, 60, 3, 2, 2, 2, 198, 199, 5,
41, 21, 2, 199, 200, 5, 47, 24, 2, 200, 201, 5, 29, 15, 2, 201, 202, 5,
15, 8, 2, 202, 62, 3, 2, 2, 2, 203, 204, 5, 51, 26, 2, 204, 205, 5, 21,
11, 2, 205, 206, 5, 15, 8, 2, 206, 207, 5, 33, 17, 2, 207, 64, 3, 2, 2,
2, 208, 209, 5, 45, 23, 2, 209, 210, 5, 21, 11, 2, 210, 211, 5, 15, 8,
2, 211, 212, 5, 33, 17, 2, 212, 66, 3, 2, 2, 2, 213, 214, 7, 40, 2, 2,
214, 215, 7, 40, 2, 2, 215, 68, 3, 2, 2, 2, 216, 217, 7, 126, 2, 2, 217,
218, 7, 126, 2, 2, 218, 70, 3, 2, 2, 2, 219, 220, 5, 45, 23, 2, 220, 221,
5, 41, 21, 2, 221, 222, 5, 47, 24, 2, 222, 223, 5, 15, 8, 2, 223, 72, 3,
2, 2, 2, 224, 225, 5, 17, 9, 2, 225, 226, 5, 7, 4, 2, 226, 227, 5, 29,
15, 2, 227, 228, 5, 43, 22, 2, 228, 229, 5, 15, 8, 2, 229, 74, 3, 2, 2,
2, 230, 231, 5, 33, 17, 2, 231, 232, 5, 47, 24, 2, 232, 233, 5, 29, 15,
2, 233, 234, 5, 29, 15, 2, 234, 76, 3, 2, 2, 2, 235, 236, 5, 33, 17, 2,
236, 237, 5, 35, 18, 2, 237, 238, 5, 45, 23, 2, 238, 78, 3, 2, 2, 2, 239,
240, 5, 43, 22, 2, 240, 241, 5, 7, 4, 2, 241, 242, 5, 29, 15, 2, 242, 243,
5, 23, 12, 2, 243, 244, 5, 15, 8, 2, 244, 245, 5, 33, 17, 2, 245, 246,
5, 11, 6, 2, 246, 247, 5, 15, 8, 2, 247, 80, 3, 2, 2, 2, 248, 252, 9, 29,
2, 2, 249, 251, 9, 30, 2, 2, 250, 249, 3, 2, 2, 2, 251, 254, 3, 2, 2, 2,
252, 250, 3, 2, 2, 2, 252, 253, 3, 2, 2, 2, 253, 82, 3, 2, 2, 2, 254, 252,
3, 2, 2, 2, 255, 259, 5, 81, 41, 2, 256, 257, 5, 117, 59, 2, 257, 258,
5, 81, 41, 2, 258, 260, 3, 2, 2, 2, 259, 256, 3, 2, 2, 2, 260, 261, 3,
2, 2, 2, 261, 259, 3, 2, 2, 2, 261, 262, 3, 2, 2, 2, 262, 84, 3, 2, 2,
2, 263, 264, 7, 45, 2, 2, 264, 86, 3, 2, 2, 2, 265, 266, 7, 47, 2, 2, 266,
88, 3, 2, 2, 2, 267, 268, 7, 49, 2, 2, 268, 90, 3, 2, 2, 2, 269, 270, 7,
44, 2, 2, 270, 92, 3, 2, 2, 2, 271, 272, 7, 63, 2, 2, 272, 273, 7, 63,
2, 2, 273, 94, 3, 2, 2, 2, 274, 275, 7, 63, 2, 2, 275, 96, 3, 2, 2, 2,
276, 277, 7, 64, 2, 2, 277, 98, 3, 2, 2, 2, 278, 279, 7, 62, 2, 2, 279,
100, 3, 2, 2, 2, 280, 281, 7, 64, 2, 2, 281, 282, 7, 63, 2, 2, 282, 102,
3, 2, 2, 2, 283, 284, 7, 62, 2, 2, 284, 285, 7, 63, 2, 2, 285, 104, 3,
2, 2, 2, 286, 287, 7, 35, 2, 2, 287, 288, 7, 63, 2, 2, 288, 106, 3, 2,
2, 2, 289, 290, 7, 61, 2, 2, 290, 108, 3, 2, 2, 2, 291, 292, 7, 125, 2,
2, 292, 110, 3, 2, 2, 2, 293, 294, 7, 127, 2, 2, 294, 112, 3, 2, 2, 2,
295, 296, 7, 42, 2, 2, 296, 114, 3, 2, 2, 2, 297, 298, 7, 43, 2, 2, 298,
116, 3, 2, 2, 2, 299, 300, 7, 48, 2, 2, 300, 118, 3, 2, 2, 2, 301, 309,
7, 36, 2, 2, 302, 303, 7, 94, 2, 2, 303, 308, 11, 2, 2, 2, 304, 305, 7,
36, 2, 2, 305, 308, 7, 36, 2, 2, 306, 308, 10, 31, 2, 2, 307, 302, 3, 2,
2, 2, 307, 304, 3, 2, 2, 2, 307, 306, 3, 2, 2, 2, 308, 311, 3, 2, 2, 2,
309, 307, 3, 2, 2, 2, 309, 310, 3, 2, 2, 2, 310, 312, 3, 2, 2, 2, 311,
309, 3, 2, 2, 2, 312, 313, 7, 36, 2, 2, 313, 120, 3, 2, 2, 2, 314, 322,
7, 41, 2, 2, 315, 316, 7, 94, 2, 2, 316, 321, 11, 2, 2, 2, 317, 318, 7,
41, 2, 2, 318, 321, 7, 41, 2, 2, 319, 321, 10, 32, 2, 2, 320, 315, 3, 2,
2, 2, 320, 317, 3, 2, 2, 2, 320, 319, 3, 2, 2, 2, 321, 324, 3, 2, 2, 2,
322, 320, 3, 2, 2, 2, 322, 323, 3, 2, 2, 2, 323, 325, 3, 2, 2, 2, 324,
322, 3, 2, 2, 2, 325, 326, 7, 41, 2, 2, 326, 122, 3, 2, 2, 2, 327, 329,
5, 5, 3, 2, 328, 327, 3, 2, 2, 2, 329, 330, 3, 2, 2, 2, 330, 328, 3, 2,
2, 2, 330, 331, 3, 2, 2, 2, 331, 124, 3, 2, 2, 2, 332, 334, 5, 5, 3, 2,
333, 332, 3, 2, 2, 2, 334, 335, 3, 2, 2, 2, 335, 333, 3, 2, 2, 2, 335,
336, 3, 2, 2, 2, 336, 338, 3, 2, 2, 2, 337, 333, 3, 2, 2, 2, 337, 338,
3, 2, 2, 2, 338, 339, 3, 2, 2, 2, 339, 341, 7, 48, 2, 2, 340, 342, 5, 5,
3, 2, 341, 340, 3, 2, 2, 2, 342, 343, 3, 2, 2, 2, 343, 341, 3, 2, 2, 2,
343, 344, 3, 2, 2, 2, 344, 376, 3, 2, 2, 2, 345, 347, 5, 5, 3, 2, 346,
345, 3, 2, 2, 2, 347, 348, 3, 2, 2, 2, 348, 346, 3, 2, 2, 2, 348, 349,
3, 2, 2, 2, 349, 350, 3, 2, 2, 2, 350, 351, 7, 48, 2, 2, 351, 352, 5, 59,
30, 2, 352, 376, 3, 2, 2, 2, 353, 355, 5, 5, 3, 2, 354, 353, 3, 2, 2, 2,
355, 356, 3, 2, 2, 2, 356, 354, 3, 2, 2, 2, 356, 357, 3, 2, 2, 2, 357,
359, 3, 2, 2, 2, 358, 354, 3, 2, 2, 2, 358, 359, 3, 2, 2, 2, 359, 360,
3, 2, 2, 2, 360, 362, 7, 48, 2, 2, 361, 363, 5, 5, 3, 2, 362, 361, 3, 2,
2, 2, 363, 364, 3, 2, 2, 2, 364, 362, 3, 2, 2, 2, 364, 365, 3, 2, 2, 2,
365, 366, 3, 2, 2, 2, 366, 367, 5, 59, 30, 2, 367, 376, 3, 2, 2, 2, 368,
370, 5, 5, 3, 2, 369, 368, 3, 2, 2, 2, 370, 371, 3, 2, 2, 2, 371, 369,
3, 2, 2, 2, 371, 372, 3, 2, 2, 2, 372, 373, 3, 2, 2, 2, 373, 374, 5, 59,
30, 2, 374, 376, 3, 2, 2, 2, 375, 337, 3, 2, 2, 2, 375, 346, 3, 2, 2, 2,
375, 358, 3, 2, 2, 2, 375, 369, 3, 2, 2, 2, 376, 126, 3, 2, 2, 2, 377,
379, 9, 33, 2, 2, 378, 377, 3, 2, 2, 2, 379, 380, 3, 2, 2, 2, 380, 378,
3, 2, 2, 2, 380, 381, 3, 2, 2, 2, 381, 382, 3, 2, 2, 2, 382, 383, 8, 64,
2, 2, 383, 128, 3, 2, 2, 2, 384, 385, 7, 49, 2, 2, 385, 386, 7, 44, 2,
2, 386, 390, 3, 2, 2, 2, 387, 389, 11, 2, 2, 2, 388, 387, 3, 2, 2, 2, 389,
392, 3, 2, 2, 2, 390, 391, 3, 2, 2, 2, 390, 388, 3, 2, 2, 2, 391, 393,
3, 2, 2, 2, 392, 390, 3, 2, 2, 2, 393, 394, 7, 44, 2, 2, 394, 395, 7, 49,
2, 2, 395, 396, 3, 2, 2, 2, 396, 397, 8, 65, 3, 2, 397, 130, 3, 2, 2, 2,
398, 399, 7, 49, 2, 2, 399, 400, 7, 49, 2, 2, 400, 404, 3, 2, 2, 2, 401,
403, 10, 34, 2, 2, 402, 401, 3, 2, 2, 2, 403, 406, 3, 2, 2, 2, 404, 402,
3, 2, 2, 2, 404, 405, 3, 2, 2, 2, 405, 407, 3, 2, 2, 2, 406, 404, 3, 2,
2, 2, 407, 408, 8, 66, 4, 2, 408, 132, 3, 2, 2, 2, 24, 2, 191, 196, 252,
261, 307, 309, 320, 322, 330, 335, 337, 343, 348, 356, 358, 364, 371, 375,
380, 390, 404, 5, 3, 64, 2, 3, 65, 3, 3, 66, 4,
}
var lexerDeserializer = antlr.NewATNDeserializer(nil)
var lexerAtn = lexerDeserializer.DeserializeFromUInt16(serializedLexerAtn)
var lexerChannelNames = []string{
"DEFAULT_TOKEN_CHANNEL", "HIDDEN",
}
var lexerModeNames = []string{
"DEFAULT_MODE",
}
var lexerLiteralNames = []string{
"", "','", "", "", "", "'&&'", "'||'", "", "", "", "", "", "", "", "'+'",
"'-'", "'/'", "'*'", "'=='", "'='", "'>'", "'<'", "'>='", "'<='", "'!='",
"';'", "'{'", "'}'", "'('", "')'", "'.'",
}
var lexerSymbolicNames = []string{
"", "", "RULE", "WHEN", "THEN", "AND", "OR", "TRUE", "FALSE", "NULL_LITERAL",
"NOT", "SALIENCE", "SIMPLENAME", "DOTTEDNAME", "PLUS", "MINUS", "DIV",
"MUL", "EQUALS", "ASSIGN", "GT", "LT", "GTE", "LTE", "NOTEQUALS", "SEMICOLON",
"LR_BRACE", "RR_BRACE", "LR_BRACKET", "RR_BRACKET", "DOT", "DQUOTA_STRING",
"SQUOTA_STRING", "DECIMAL_LITERAL", "REAL_LITERAL", "SPACE", "COMMENT",
"LINE_COMMENT",
}
var lexerRuleNames = []string{
"T__0", "DEC_DIGIT", "A", "B", "C", "D", "E", "F", "G", "H", "I", "J",
"K", "L", "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y",
"Z", "EXPONENT_NUM_PART", "RULE", "WHEN", "THEN", "AND", "OR", "TRUE",
"FALSE", "NULL_LITERAL", "NOT", "SALIENCE", "SIMPLENAME", "DOTTEDNAME",
"PLUS", "MINUS", "DIV", "MUL", "EQUALS", "ASSIGN", "GT", "LT", "GTE", "LTE",
"NOTEQUALS", "SEMICOLON", "LR_BRACE", "RR_BRACE", "LR_BRACKET", "RR_BRACKET",
"DOT", "DQUOTA_STRING", "SQUOTA_STRING", "DECIMAL_LITERAL", "REAL_LITERAL",
"SPACE", "COMMENT", "LINE_COMMENT",
}
type groolLexer struct {
*antlr.BaseLexer
channelNames []string
modeNames []string
// TODO: EOF string
}
var lexerDecisionToDFA = make([]*antlr.DFA, len(lexerAtn.DecisionToState))
func init() {
for index, ds := range lexerAtn.DecisionToState {
lexerDecisionToDFA[index] = antlr.NewDFA(ds, index)
}
}
func NewgroolLexer(input antlr.CharStream) *groolLexer {
l := new(groolLexer)
l.BaseLexer = antlr.NewBaseLexer(input)
l.Interpreter = antlr.NewLexerATNSimulator(l, lexerAtn, lexerDecisionToDFA, antlr.NewPredictionContextCache())
l.channelNames = lexerChannelNames
l.modeNames = lexerModeNames
l.RuleNames = lexerRuleNames
l.LiteralNames = lexerLiteralNames
l.SymbolicNames = lexerSymbolicNames
l.GrammarFileName = "grool.g4"
// TODO: l.EOF = antlr.TokenEOF
return l
}
// groolLexer tokens.
const (
groolLexerT__0 = 1
groolLexerRULE = 2
groolLexerWHEN = 3
groolLexerTHEN = 4
groolLexerAND = 5
groolLexerOR = 6
groolLexerTRUE = 7
groolLexerFALSE = 8
groolLexerNULL_LITERAL = 9
groolLexerNOT = 10
groolLexerSALIENCE = 11
groolLexerSIMPLENAME = 12
groolLexerDOTTEDNAME = 13
groolLexerPLUS = 14
groolLexerMINUS = 15
groolLexerDIV = 16
groolLexerMUL = 17
groolLexerEQUALS = 18
groolLexerASSIGN = 19
groolLexerGT = 20
groolLexerLT = 21
groolLexerGTE = 22
groolLexerLTE = 23
groolLexerNOTEQUALS = 24
groolLexerSEMICOLON = 25
groolLexerLR_BRACE = 26
groolLexerRR_BRACE = 27
groolLexerLR_BRACKET = 28
groolLexerRR_BRACKET = 29
groolLexerDOT = 30
groolLexerDQUOTA_STRING = 31
groolLexerSQUOTA_STRING = 32
groolLexerDECIMAL_LITERAL = 33
groolLexerREAL_LITERAL = 34
groolLexerSPACE = 35
groolLexerCOMMENT = 36
groolLexerLINE_COMMENT = 37
)
func (l *groolLexer) Action(localctx antlr.RuleContext, ruleIndex, actionIndex int) {
switch ruleIndex {
case 62:
l.SPACE_Action(localctx, actionIndex)
case 63:
l.COMMENT_Action(localctx, actionIndex)
case 64:
l.LINE_COMMENT_Action(localctx, actionIndex)
default:
panic("No registered action for: " + fmt.Sprint(ruleIndex))
}
}
func (l *groolLexer) SPACE_Action(localctx antlr.RuleContext, actionIndex int) {
switch actionIndex {
case 0:
l.Skip()
default:
panic("No registered action for: " + fmt.Sprint(actionIndex))
}
}
func (l *groolLexer) COMMENT_Action(localctx antlr.RuleContext, actionIndex int) {
switch actionIndex {
case 1:
l.Skip()
default:
panic("No registered action for: " + fmt.Sprint(actionIndex))
}
}
func (l *groolLexer) LINE_COMMENT_Action(localctx antlr.RuleContext, actionIndex int) {
switch actionIndex {
case 2:
l.Skip()
default:
panic("No registered action for: " + fmt.Sprint(actionIndex))
}
}
// Generated from grool.g4 by ANTLR 4.7.
package parser // grool
import "github.com/antlr/antlr4/runtime/Go/antlr"
// groolListener is a complete listener for a parse tree produced by groolParser.
type groolListener interface {
antlr.ParseTreeListener
// EnterRoot is called when entering the root production.
EnterRoot(c *RootContext)
// EnterRuleEntry is called when entering the ruleEntry production.
EnterRuleEntry(c *RuleEntryContext)
// EnterSalience is called when entering the salience production.
EnterSalience(c *SalienceContext)
// EnterRuleName is called when entering the ruleName production.
EnterRuleName(c *RuleNameContext)
// EnterRuleDescription is called when entering the ruleDescription production.
EnterRuleDescription(c *RuleDescriptionContext)
// EnterWhenScope is called when entering the whenScope production.
EnterWhenScope(c *WhenScopeContext)
// EnterThenScope is called when entering the thenScope production.
EnterThenScope(c *ThenScopeContext)
// EnterAssignExpressions is called when entering the assignExpressions production.
EnterAssignExpressions(c *AssignExpressionsContext)
// EnterAssignExpression is called when entering the assignExpression production.
EnterAssignExpression(c *AssignExpressionContext)
// EnterAssignment is called when entering the assignment production.
EnterAssignment(c *AssignmentContext)
// EnterExpression is called when entering the expression production.
EnterExpression(c *ExpressionContext)
// EnterPredicate is called when entering the predicate production.
EnterPredicate(c *PredicateContext)
// EnterExpressionAtom is called when entering the expressionAtom production.
EnterExpressionAtom(c *ExpressionAtomContext)
// EnterMethodCall is called when entering the methodCall production.
EnterMethodCall(c *MethodCallContext)
// EnterFunctionCall is called when entering the functionCall production.
EnterFunctionCall(c *FunctionCallContext)
// EnterFunctionArgs is called when entering the functionArgs production.
EnterFunctionArgs(c *FunctionArgsContext)
// EnterLogicalOperator is called when entering the logicalOperator production.
EnterLogicalOperator(c *LogicalOperatorContext)
// EnterVariable is called when entering the variable production.
EnterVariable(c *VariableContext)
// EnterMathOperator is called when entering the mathOperator production.
EnterMathOperator(c *MathOperatorContext)
// EnterComparisonOperator is called when entering the comparisonOperator production.
EnterComparisonOperator(c *ComparisonOperatorContext)
// EnterConstant is called when entering the constant production.
EnterConstant(c *ConstantContext)
// EnterDecimalLiteral is called when entering the decimalLiteral production.
EnterDecimalLiteral(c *DecimalLiteralContext)
// EnterRealLiteral is called when entering the realLiteral production.
EnterRealLiteral(c *RealLiteralContext)
// EnterStringLiteral is called when entering the stringLiteral production.
EnterStringLiteral(c *StringLiteralContext)
// EnterBooleanLiteral is called when entering the booleanLiteral production.
EnterBooleanLiteral(c *BooleanLiteralContext)
// ExitRoot is called when exiting the root production.
ExitRoot(c *RootContext)
// ExitRuleEntry is called when exiting the ruleEntry production.
ExitRuleEntry(c *RuleEntryContext)
// ExitSalience is called when exiting the salience production.
ExitSalience(c *SalienceContext)
// ExitRuleName is called when exiting the ruleName production.
ExitRuleName(c *RuleNameContext)
// ExitRuleDescription is called when exiting the ruleDescription production.
ExitRuleDescription(c *RuleDescriptionContext)
// ExitWhenScope is called when exiting the whenScope production.
ExitWhenScope(c *WhenScopeContext)
// ExitThenScope is called when exiting the thenScope production.
ExitThenScope(c *ThenScopeContext)
// ExitAssignExpressions is called when exiting the assignExpressions production.
ExitAssignExpressions(c *AssignExpressionsContext)
// ExitAssignExpression is called when exiting the assignExpression production.
ExitAssignExpression(c *AssignExpressionContext)
// ExitAssignment is called when exiting the assignment production.
ExitAssignment(c *AssignmentContext)
// ExitExpression is called when exiting the expression production.
ExitExpression(c *ExpressionContext)
// ExitPredicate is called when exiting the predicate production.
ExitPredicate(c *PredicateContext)
// ExitExpressionAtom is called when exiting the expressionAtom production.
ExitExpressionAtom(c *ExpressionAtomContext)
// ExitMethodCall is called when exiting the methodCall production.
ExitMethodCall(c *MethodCallContext)
// ExitFunctionCall is called when exiting the functionCall production.
ExitFunctionCall(c *FunctionCallContext)
// ExitFunctionArgs is called when exiting the functionArgs production.
ExitFunctionArgs(c *FunctionArgsContext)
// ExitLogicalOperator is called when exiting the logicalOperator production.
ExitLogicalOperator(c *LogicalOperatorContext)
// ExitVariable is called when exiting the variable production.
ExitVariable(c *VariableContext)
// ExitMathOperator is called when exiting the mathOperator production.
ExitMathOperator(c *MathOperatorContext)
// ExitComparisonOperator is called when exiting the comparisonOperator production.
ExitComparisonOperator(c *ComparisonOperatorContext)
// ExitConstant is called when exiting the constant production.
ExitConstant(c *ConstantContext)
// ExitDecimalLiteral is called when exiting the decimalLiteral production.
ExitDecimalLiteral(c *DecimalLiteralContext)
// ExitRealLiteral is called when exiting the realLiteral production.
ExitRealLiteral(c *RealLiteralContext)
// ExitStringLiteral is called when exiting the stringLiteral production.
ExitStringLiteral(c *StringLiteralContext)
// ExitBooleanLiteral is called when exiting the booleanLiteral production.
ExitBooleanLiteral(c *BooleanLiteralContext)
}
// This is a comment
// And this
/* And also this */
/*
As well as this
*/
rule RuleOne "Some rule description." salience 10 {
when
(someContext.attributeA.attributeA == 123 &&
someContext.attributeA.attributeB > 123 ||
someContext.attributeA.attributeB < 123 &&
someContext.attributeA.attributeB >= 123 &&
(someContext.attributeA.attributeB <= 123 && someContext.attributeA.attributeB != 123) &&
someContext.attributeA.attributeB > 123) ||
someContext.subContext.methodAbc( 23 + someContext.subContext.another() )
||
someContext.attributeA.attributeA == 123.32
||
someContext.attributeA.attributeS == "abcdefg"
||
trim(someContext.attributeA.attributeS) == "abcdefg"
||
someContext.date.value < now( 12 - 32)
then
otherContext.property.attr1 = 12; // comment here
otherContext.property.attr1 = otherContext.property.attr1-12;
/*
another comment
*/
otherContext.property.attr1 = func(otherContext.property.attr1-12) / 45;
}
rule RuleTwo "Some rule description." {
when
(someContext.attributeA.attributeA == 123 &&
someContext.attributeA.attributeB > 123 ||
someContext.attributeA.attributeB < 123 &&
someContext.attributeA.attributeB >= 123 &&
(someContext.attributeA.attributeB <= 123 && someContext.attributeA.attributeB != 123) &&
someContext.attributeA.attributeB > 123)
||
someContext.attributeA.attributeA == 123.32
||
someContext.attributeA.attributeS == "abcdefg"
||
trim(someContext.attributeA.attributeS) == "abcdefg"
||
someContext.date.value < now()
then
otherContext.property.attr1 = 12;
otherContext.property.attr1 = otherContext.property.attr1-12;
// commented code
// otherContext.property.attr1 = func(otherContext.property.attr1-12) / 45;
log("this is to be logged");
}
\ No newline at end of file
rule TaxingLuxuryItems "When its a luxury Item, you tax them 15 percent." salience 10 {
when
Purchase.IgnoredPurchase == false && Purchase.Tax == 0 && Purchase.ItemType == "LUXURY"
then
Purchase.Tax = Purchase.Price + (Purchase.Price * 0.15);
}
rule TaxingNormalItems "When its a Normal Item, you tax them 10 percent." salience 8 {
when
Purchase.IgnoredPurchase == false && Purchase.Tax == 0 && Purchase.ItemType == "NORMAL"
then
Purchase.Tax = Purchase.Price + (Purchase.Price * 0.1);
}
rule TaxingOtherTypeItems "When its not Normal or Luxury Item, you tax them 20 percent." salience 7 {
when
Purchase.IgnoredPurchase == false && Purchase.Tax == 0 && Purchase.ItemType != "NORMAL" && Purchase.ItemType != "LUXURY"
then
Purchase.Tax = Purchase.Price + (Purchase.Price * 0.2);
}
rule CalculatePriceAfterTax "When tax is calculated, time to calculate price after tax" {
when
Purchase.Tax > 0 && Purchase.PriceAfterTax == 0
then
Purchase.PriceAfterTax = Purchase.Price + Purchase.Tax;
}
rule SumUpPurchase "When price after tax calculated, sum it up" {
when
Purchase.PriceAfterTax > 0
then
CashFlow.PurchaseCount = PurchaseCount + 1;
CashFlow.TotalPurchases = CashFlow.TotalPurchases + Purchase.Price;
CashFlow.TotalTax = CashFlow.TotalTax + Purchase.Tax;
CashFlow.PurchasesAfterTax = CashFlow.PurchasesAfterTax + Purchase.PriceAfterTax;
Retract("SumUpPurchase");
}
rule OnlyCalculatePurchaseInYear2019 "All other purchase dated not in 2019, we should ignore" salience 100 {
when
Purchase.IgnoredPurchase == false && Purchase.PurchaseDate.Year() != 2019 && Purchase.PriceAfterTax == 0
then
Purchase.IgnoredPurchase = true;
Retract("OnlyCalculatePurchaseInYear2019");
}
package builder
import (
"github.com/antlr/antlr4/runtime/Go/antlr"
"github.com/juju/errors"
antlr2 "github.com/newm4n/grool/antlr"
"github.com/newm4n/grool/antlr/parser"
"github.com/newm4n/grool/model"
"github.com/newm4n/grool/pkg"
log "github.com/sirupsen/logrus"
)
// NewRuleBuilder creates new RuleBuilder instance. This builder will add all loaded rules into the specified knowledgebase.
func NewRuleBuilder(KnowledgeBase *model.KnowledgeBase) *RuleBuilder {
return &RuleBuilder{
KnowledgeBase: KnowledgeBase,
}
}
// RuleBuilder builds rule from DRL script into contained KnowledgeBase
type RuleBuilder struct {
KnowledgeBase *model.KnowledgeBase
}
// MustBuildRuleFromResources is similar to BuildRuleFromResources, with the difference is, it will panic if rule script contains error.
func (builder *RuleBuilder) MustBuildRuleFromResources(resource []pkg.Resource) {
for _, v := range resource {
err := builder.BuildRuleFromResource(v)
if err != nil {
panic(err)
}
}
}
// MustBuildRuleFromResource is similar to BuildRuleFromResource, with the difference is, it will panic if rule script contains error.
func (builder *RuleBuilder) MustBuildRuleFromResource(resource pkg.Resource) {
if err := builder.BuildRuleFromResource(resource); err != nil {
panic(err)
}
}
// BuildRuleFromResources will load rules from multiple resources. It will return an error if it encounter an error on the first script it found.
func (builder *RuleBuilder) BuildRuleFromResources(resource []pkg.Resource) error {
for _, v := range resource {
err := builder.BuildRuleFromResource(v)
if err != nil {
return errors.Trace(err)
}
}
return nil
}
// BuildRuleFromResource will load rules from a single resource. It will return an error if it encounter an error on the specified resource.
func (builder *RuleBuilder) BuildRuleFromResource(resource pkg.Resource) error {
data, err := resource.Load()
if err != nil {
return errors.Trace(err)
}
sdata := string(data)
is := antlr.NewInputStream(sdata)
lexer := parser.NewgroolLexer(is)
stream := antlr.NewCommonTokenStream(lexer, antlr.TokenDefaultChannel)
listener := antlr2.NewGroolParserListener(builder.KnowledgeBase)
psr := parser.NewgroolParser(stream)
psr.BuildParseTrees = true
antlr.ParseTreeWalkerDefault.Walk(listener, psr.Root())
if len(listener.ParseErrors) > 0 {
log.Errorf("Loading rule resource : %s failed. Got %d errors. 1st error : %v", resource.String(), len(listener.ParseErrors), listener.ParseErrors[0])
return errors.Errorf("error were found before builder bailing out. %d errors. 1st error : %v", len(listener.ParseErrors), listener.ParseErrors[0])
}
log.Debugf("Loading rule resource : %s success", resource.String())
return nil
}
package context
import (
"fmt"
"github.com/juju/errors"
"github.com/newm4n/grool/pkg"
"reflect"
"strings"
)
var (
FactNotFoundError = errors.New("Fact not found")
FactRetractedError = errors.New("Fact is retracted")
)
// NewDataContext will create a new DataContext instance
func NewDataContext() *DataContext {
return &DataContext{
ObjectStore: make(map[string]interface{}),
Retracted: make([]string, 0),
}
}
// DataContext holds all structs instance to be used in rule execution environment.
type DataContext struct {
ObjectStore map[string]interface{}
Retracted []string
VariableChangeCount uint64
}
// Retract temporary retract a fact from data context, making it unavailable for evaluation or modification.
func (ctx *DataContext) Retract(key string) {
ctx.Retracted = append(ctx.Retracted, key)
}
// Add will add struct instance into rule execution context
func (ctx *DataContext) Add(key string, obj interface{}) error {
objVal := reflect.ValueOf(obj)
if objVal.Kind() != reflect.Ptr && objVal.Elem().Kind() != reflect.Struct {
return errors.New(fmt.Sprintf("you can only insert a pointer to struct as fact. objVal = %s", objVal.Kind().String()))
}
ctx.ObjectStore[key] = obj
return nil
}
// IsRestracted checks if a key fact is currently retracted.
func (ctx *DataContext) IsRestracted(key string) bool {
for _, v := range ctx.Retracted {
if v == key {
return true
}
}
return false
}
// Reset will un-retract all fact, making them available for evaluation and modification.
func (ctx *DataContext) Reset() {
ctx.Retracted = make([]string, 0)
}
// ExecMethod will execute instance member variable using the supplied arguments.
func (ctx *DataContext) ExecMethod(methodName string, args []reflect.Value) (reflect.Value, error) {
varArray := strings.Split(methodName, ".")
if val, ok := ctx.ObjectStore[varArray[0]]; ok {
if !ctx.IsRestracted(varArray[0]) {
return traceMethod(val, varArray[1:], args)
}
return reflect.ValueOf(nil), FactRetractedError
}
return reflect.ValueOf(nil), FactNotFoundError
}
// GetType will extract type information of data in this context.
func (ctx *DataContext) GetType(variable string) (reflect.Type, error) {
varArray := strings.Split(variable, ".")
if val, ok := ctx.ObjectStore[varArray[0]]; ok {
if !ctx.IsRestracted(varArray[0]) {
return traceType(val, varArray[1:])
}
return nil, FactRetractedError
}
return nil, FactNotFoundError
}
// GetValue will get member variables Value information.
// Used by the rule execution to obtain variable value.
func (ctx *DataContext) GetValue(variable string) (reflect.Value, error) {
varArray := strings.Split(variable, ".")
if val, ok := ctx.ObjectStore[varArray[0]]; ok {
if !ctx.IsRestracted(varArray[0]) {
vval, err := traceValue(val, varArray[1:])
if err != nil {
fmt.Printf("blah %s = %v\n", variable, vval)
}
return vval, err
}
return reflect.ValueOf(nil), FactRetractedError
}
return reflect.ValueOf(nil), FactNotFoundError
}
// SetValue will set variable value of an object instance in this data context, Used by rule script to set values.
func (ctx *DataContext) SetValue(variable string, newValue reflect.Value) error {
varArray := strings.Split(variable, ".")
if val, ok := ctx.ObjectStore[varArray[0]]; ok {
if !ctx.IsRestracted(varArray[0]) {
err := traceSetValue(val, varArray[1:], newValue)
if err == nil {
ctx.VariableChangeCount++
}
return err
}
return FactRetractedError
}
return FactNotFoundError
}
func traceType(obj interface{}, path []string) (reflect.Type, error) {
switch length := len(path); {
case length == 1:
return pkg.GetAttributeType(obj, path[0])
case length > 1:
objVal, err := pkg.GetAttributeValue(obj, path[0])
if err != nil {
return nil, errors.Trace(err)
}
return traceType(pkg.ValueToInterface(objVal), path[1:])
default:
return reflect.TypeOf(obj), nil
}
}
func traceValue(obj interface{}, path []string) (reflect.Value, error) {
switch length := len(path); {
case length == 1:
return pkg.GetAttributeValue(obj, path[0])
case length > 1:
objVal, err := pkg.GetAttributeValue(obj, path[0])
if err != nil {
return objVal, errors.Trace(err)
}
return traceValue(pkg.ValueToInterface(objVal), path[1:])
default:
return reflect.ValueOf(obj), nil
}
}
func traceSetValue(obj interface{}, path []string, newValue reflect.Value) error {
switch length := len(path); {
case length == 1:
return pkg.SetAttributeValue(obj, path[0], newValue)
case length > 1:
objVal, err := pkg.GetAttributeValue(obj, path[0])
if err != nil {
return errors.Trace(err)
}
return traceSetValue(objVal, path[1:], newValue)
default:
return errors.Errorf("no attribute path specified")
}
}
func traceMethod(obj interface{}, path []string, args []reflect.Value) (reflect.Value, error) {
switch length := len(path); {
case length == 1:
// this obj is reflect.Value... it should not.
types, err := pkg.GetFunctionParameterTypes(obj, path[0])
if err != nil {
return reflect.ValueOf(nil),
errors.Errorf("error while fetching function %s() parameter types. Got %v", path[0], err)
}
if len(types) != len(args) {
return reflect.ValueOf(nil),
errors.Errorf("invalid argument count for function %s(). need %d argument while there are %d", path[0], len(types), len(args))
}
iargs := make([]interface{}, 0)
for i, t := range types {
if t.Kind() != args[i].Kind() {
if t.Kind() == reflect.Interface {
iargs = append(iargs, pkg.ValueToInterface(args[i]))
} else {
return reflect.ValueOf(nil),
errors.Errorf("invalid argument types for function %s(). argument #%d, require %s but %s", path[0], i, t.Kind().String(), args[i].Kind().String())
}
} else {
iargs = append(iargs, pkg.ValueToInterface(args[i]))
}
}
rets, err := pkg.InvokeFunction(obj, path[0], iargs)
if err != nil {
return reflect.ValueOf(nil), err
}
switch retLen := len(rets); {
case retLen > 1:
return reflect.ValueOf(rets[0]), errors.Errorf("multiple return value for function %s(). ", path[0])
case retLen == 1:
return reflect.ValueOf(rets[0]), nil
default:
return reflect.ValueOf(nil), nil
}
case length > 1:
objVal, err := pkg.GetAttributeValue(obj, path[0])
if err != nil {
return reflect.ValueOf(nil), errors.Trace(err)
}
return traceMethod(objVal, path[1:], args)
default:
return reflect.ValueOf(nil), errors.Errorf("no function path specified")
}
}
package context
type KnowledgeContext struct {
}
package context
type RuleContext struct {
}
此差异已折叠。
package model
import (
"fmt"
"github.com/newm4n/grool/context"
"reflect"
)
// ArgumentHolder is a struct part of the rule object graph.
// It holds child graph such as Variable name, Constant data, Function, Expressions, etc.
type ArgumentHolder struct {
Constant *Constant
Variable string
FunctionCall *FunctionCall
MethodCall *MethodCall
Expression *Expression
knowledgeContext *context.KnowledgeContext
ruleCtx *context.RuleContext
dataCtx *context.DataContext
}
// Initialize this ArgumentHolder instance graph before rule execution start.
func (ah *ArgumentHolder) Initialize(knowledgeContext *context.KnowledgeContext, ruleCtx *context.RuleContext, dataCtx *context.DataContext) {
ah.knowledgeContext = knowledgeContext
ah.ruleCtx = ruleCtx
ah.dataCtx = dataCtx
if ah.Constant != nil {
ah.Constant.Initialize(knowledgeContext, ruleCtx, dataCtx)
}
if ah.FunctionCall != nil {
ah.FunctionCall.Initialize(knowledgeContext, ruleCtx, dataCtx)
}
if ah.MethodCall != nil {
ah.MethodCall.Initialize(knowledgeContext, ruleCtx, dataCtx)
}
if ah.Expression != nil {
ah.Expression.Initialize(knowledgeContext, ruleCtx, dataCtx)
}
}
// Evaluate the object graph against underlined context or execute evaluation in the sub graph.
func (ah *ArgumentHolder) Evaluate() (reflect.Value, error) {
if len(ah.Variable) > 0 {
return ah.dataCtx.GetValue(ah.Variable)
}
if ah.Constant != nil {
return ah.Constant.Evaluate()
}
if ah.FunctionCall != nil {
return ah.FunctionCall.Evaluate()
}
if ah.MethodCall != nil {
return ah.MethodCall.Evaluate()
}
if ah.Expression != nil {
return ah.Expression.Evaluate()
}
return reflect.ValueOf(nil), fmt.Errorf("argument holder stores no value")
}
package model
import (
"github.com/juju/errors"
"github.com/newm4n/grool/context"
"reflect"
)
// AssignExpressions contains list of assignment expression in the "then" scope.
type AssignExpressions struct {
ExpressionList []*AssignExpression
knowledgeContext *context.KnowledgeContext
ruleCtx *context.RuleContext
dataCtx *context.DataContext
}
// Initialize will initialize this graph with context.
func (ae *AssignExpressions) Initialize(knowledgeContext *context.KnowledgeContext, ruleCtx *context.RuleContext, dataCtx *context.DataContext) {
ae.knowledgeContext = knowledgeContext
ae.ruleCtx = ruleCtx
ae.dataCtx = dataCtx
if ae.ExpressionList != nil {
for _, val := range ae.ExpressionList {
val.Initialize(knowledgeContext, ruleCtx, dataCtx)
}
}
}
// Evaluate the object graph against underlined context or execute evaluation in the sub graph.
func (ae *AssignExpressions) Evaluate() (reflect.Value, error) {
for _, v := range ae.ExpressionList {
_, err := v.Evaluate()
if err != nil {
return reflect.ValueOf(nil), errors.Trace(err)
}
}
return reflect.ValueOf(nil), nil
}
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册