1/**
2 * \file
3 * \brief This file contains functions to generate Eclipse CLP terms based on
4 * the AST of a given record.
5 */
6
7/*
8 * Copyright (c) 2011, ETH Zurich.
9 * All rights reserved.
10 *
11 * This file is distributed under the terms in the attached LICENSE file.
12 * If you do not find this file, copies can be found by writing to:
13 * ETH Zurich D-INFK, Haldeneggsteig 4, CH-8092 Zurich. Attn: Systems Group.
14 */
15
16#include <stdlib.h>
17#include <stdio.h>
18#include <string.h>
19#include <assert.h>
20#include <stdarg.h>
21
22#include <barrelfish/barrelfish.h>
23
24#include "code_generator.h"
25
26// forward decl
27static inline struct pword_pair create_constraint(struct ast_object*);
28
29struct pword_pair {
30    bool is_attribute;
31    pword value;
32    pword op;
33};
34
35static inline struct pword_pair visit_attribute_right(struct ast_object* p)
36{
37    struct pword_pair terms;
38    terms.is_attribute = true;
39
40    switch (p->type) {
41    case nodeType_Ident:
42        terms.value = ec_atom(ec_did(p->u.in.str, 0));
43        break;
44
45    case nodeType_String:
46        assert(p->u.sn.str != NULL);
47        terms.value = ec_string(p->u.sn.str);
48        break;
49
50    case nodeType_Float:
51        terms.value = ec_double(p->u.fn.value);
52        break;
53
54    case nodeType_Constant:
55        terms.value = ec_long(p->u.cn.value);
56        break;
57
58    case nodeType_Variable:
59        terms.value = ec_newvar();
60        break;
61
62    case nodeType_Constraint:
63        terms = create_constraint(p);
64        break;
65
66    default:
67        assert(!"Should not happen, check your parser!");
68        break;
69
70    }
71
72    return terms;
73}
74
75static inline struct pword_pair create_constraint(struct ast_object* p)
76{
77    assert(p != NULL);
78    assert(p->type == nodeType_Constraint);
79
80    struct pword_pair terms = visit_attribute_right(p->u.cnsn.value);
81    terms.is_attribute = false;
82
83    switch (p->u.cnsn.op) {
84    case constraint_GT:
85        terms.op = ec_atom(ec_did(">", 2));
86        break;
87
88    case constraint_GE:
89        terms.op = ec_atom(ec_did(">=", 2));
90        break;
91
92    case constraint_LT:
93        terms.op = ec_atom(ec_did("<", 2));
94        break;
95
96    case constraint_LE:
97        terms.op = ec_atom(ec_did("<=", 2));
98        break;
99
100    case constraint_EQ:
101        terms.op = ec_atom(ec_did("==", 2));
102        break;
103
104    case constraint_NE:
105        terms.op = ec_atom(ec_did("!=", 2));
106        break;
107
108    case constraint_REGEX:
109        terms.op = ec_atom(ec_did("match", 0));
110        break;
111
112    default:
113        assert(!"OP code not supported");
114        break;
115    }
116
117    return terms;
118}
119
120static void translate(struct ast_object* p, struct skb_ec_terms* ss)
121{
122    assert(p != NULL);
123    assert(p->type == nodeType_Object);
124
125    ss->attribute_list = ec_nil();
126    ss->constraint_list = ec_nil();
127
128    struct ast_object* name = p->u.on.name;
129
130    if (name->type == nodeType_Ident) {
131        dident name_id = ec_did(name->u.in.str, 0);
132        ss->name = ec_atom(name_id);
133    } else if (name->type == nodeType_Variable) {
134        ss->name = ec_newvar();
135    } else if (name->type == nodeType_Constraint) {
136        assert(name->u.cnsn.op == constraint_REGEX);
137        // Construct match term for name regex
138        dident constraint = ec_did("name_constraint", 1);
139        pword regex = ec_string(name->u.cnsn.value->u.sn.str);
140        pword constraint_term = ec_term(constraint, regex);
141        ss->name = constraint_term;
142    }
143    else {
144        assert(!"Scan types not allowed here");
145    }
146
147
148    struct ast_object* iter = p->u.on.attrs;
149    for (; iter != NULL; iter = iter->u.an.next) {
150        assert(iter->type == nodeType_Attribute);
151        struct ast_object* left = iter->u.an.attr->u.pn.left;
152        struct ast_object* right = iter->u.an.attr->u.pn.right;
153
154        dident attr_id = ec_did(left->u.in.str, 0);
155        pword left_term = ec_atom(attr_id);
156
157        struct pword_pair right_terms = visit_attribute_right(right);
158
159        if (right_terms.is_attribute) {
160            pword entry = ec_term(ec_did("val", 2), left_term,
161                    right_terms.value);
162            ss->attribute_list = ec_list(entry, ss->attribute_list);
163        } else { // is constraint
164            dident constraint = ec_did("constraint", 3);
165            pword entry = ec_term(constraint, left_term, right_terms.op,
166                    right_terms.value);
167            ss->constraint_list = ec_list(entry, ss->constraint_list);
168        }
169    }
170
171}
172
173errval_t transform_record(struct ast_object* ast, struct skb_ec_terms* record)
174{
175    assert(ast != NULL);
176    translate(ast, record);
177
178    return SYS_ERR_OK;
179}
180
181